# Matplotlib

请根据笔记的写作日期,选择性阅读。

作者: 放羊的大少爷
Home: joynoting.com
写作日期: 2019-02-13
系统: Mac@10.14.3
软件版本:
Python@3.7.2
Anaconda Navigator@1.9.6
matplotlib@3.0.2
seaborn@0.9.0
basemap@1.2.0
参考:
《Python Data Science Handbook》
matplotlib


# 4.1 绘图

# 4.1.2 设置绘图样式

plt.style.use("classic")
1

# 4.1.3 绘图

  1. 在脚本中运行绘图

脚本中绘图需要使用一次 plt.show() 显示图像。

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)

plt.plot(x, np.sin(x))
plt.plot(x, np.cos(x))

plt.show()
1
2
3
4
5
6
7
8
9

png

  1. 在 jupyter notebook 中绘图
# 使用 %matplotlib 之后就不用  plt.show() 了
%matplotlib

# 启动交互式图形
%matplotlib notebook

# 启动静态图形
%matplotlib inline
1
2
3
4
5
6
7
8
%matplotlib notebook
1
# 示例
import numpy as np
x = np.linspace(0, 10, 100)

fig = plt.figure()
plt.plot(x, np.sin(x), '-')
plt.plot(x, np.cos(x), '--');
1
2
3
4
5
6
7

png

# 4.1.4 将图形保存为文件

# 保存图形
fig.savefig('my_figure.png')

# 显示图形
from IPython.display import Image
Image('my_figure.png')

# 查看支持保存的图形格式
fig.canvas.get_supported_filetypes()
1
2
3
4
5
6
7
8
9
# 查看支持保存的图形格式
fig.canvas.get_supported_filetypes()
1
2
{'ps': 'Postscript',
 'eps': 'Encapsulated Postscript',
 'pdf': 'Portable Document Format',
 'pgf': 'PGF code for LaTeX',
 'png': 'Portable Network Graphics',
 'raw': 'Raw RGBA bitmap',
 'rgba': 'Raw RGBA bitmap',
 'svg': 'Scalable Vector Graphics',
 'svgz': 'Scalable Vector Graphics',
 'jpg': 'Joint Photographic Experts Group',
 'jpeg': 'Joint Photographic Experts Group',
 'tif': 'Tagged Image File Format',
 'tiff': 'Tagged Image File Format'}

# 4.1.5 显示图片

# 显示图片
import matplotlib.pyplot as plt
import matplotlib.image as mpimg

img = mpimg.imread('figures/water.jpg')
# 显示图片
plt.imshow(img)
# 不显示坐标轴
plt.axis('off')
plt.show()
1
2
3
4
5
6
7
8
9
10

png

# 4.2 绘图风格

# 4.2.1 MATLAB 绘图风格(不推荐)

# 4.2.2 面向对象接口(推荐 )

# 创建图形
fig = plt.figure()

# 创建坐标轴
ax = plt.axes()
1
2
3
4
5

图形(设置标签等等): 能容纳各种坐标轴、图形、文字和标签的容器。

坐标轴(绘图): 带有刻度和标签的矩形,最终会包含所有的可视化图形元素。

# 面向对象接口
# First create a grid of plots
# ax will be an array of two Axes objects
fig, ax = plt.subplots(2)

# Call plot() method on the appropriate object
ax[0].plot(x, np.sin(x))
ax[1].plot(x, np.cos(x));
1
2
3
4
5
6
7
8

png

# 4.3 线形图

# 4.3.1 调整颜色与风格

# 颜色
plt.plot() 的 color 参数
# 线条风格
plt.plot() 的 color 参数
1
2
3
4
# 颜色
plt.plot(x, np.sin(x - 0), color='blue')        # specify color by name
plt.plot(x, np.sin(x - 1), color='g')           # short color code (rgbcmyk)
plt.plot(x, np.sin(x - 2), color='0.75')        # 0~1之间的灰度值
plt.plot(x, np.sin(x - 3), color='#FFDD44')     # Hex code (RRGGBB from 00 to FF)
plt.plot(x, np.sin(x - 4), color=(1.0,0.2,0.3)) # RGB tuple, values 0 to 1
plt.plot(x, np.sin(x - 5), color='chartreuse'); # all HTML color names supported
1
2
3
4
5
6
7

png

# 线条风格
plt.plot(x, x + 0, linestyle='solid')
plt.plot(x, x + 1, linestyle='dashed')
plt.plot(x, x + 2, linestyle='dashdot')
plt.plot(x, x + 3, linestyle='dotted');

# For short, you can use the following codes:
plt.plot(x, x + 4, linestyle='-')  # solid 实线
plt.plot(x, x + 5, linestyle='--') # dashed 虚线
plt.plot(x, x + 6, linestyle='-.') # dashdot 点划线
plt.plot(x, x + 7, linestyle=':');  # dotted 实点线
1
2
3
4
5
6
7
8
9
10
11

# 4.3.2 调整坐标轴上下限

方法一:

plt.xlim([xmin, xmax])
plt.ylim([ymin, ymax])
1
2

方法二:

plt.axis([xmin, xmax, ymin, ymax])
1
# 自动收缩,不留空白
plt.axis('tight')

# 图像显示为1:1
plt.axis('equal')
1
2
3
4
5
# 正序
plt.plot(x, np.sin(x))

plt.xlim(0, 10)
plt.ylim(-1.2, 1.2);
1
2
3
4
5

png

# 逆序
plt.plot(x, np.sin(x))

plt.xlim(10, 0);
plt.ylim(1.2, -1.2);
1
2
3
4
5

png

# 4.3.3 设置图形标签

# 设置标题
plt.title()
# 设置 x 轴标签
plt.xlabel()
# 设置 y 轴标签
plt.ylabel()
# 设置图例
plt.plot() 中的 label 参数
plt.legend()
1
2
3
4
5
6
7
8
9
plt.title("A Sine Curve")
plt.xlabel("x")
plt.ylabel("sin(x)")

plt.plot(x, np.sin(x), '-g', label='sin(x)')
plt.plot(x, np.cos(x), ':b', label='cos(x)')
plt.axis('equal')

plt.legend();
1
2
3
4
5
6
7
8
9

png

# 4.4 简易散点图

# 4.4.1 plt.plot绘制散点图

rng = np.random.RandomState(0)
for marker in ['o', '.', ',', 'x', '+', 'v', '^', '<', '>', 's', 'd']:
    plt.plot(
        rng.rand(5), rng.rand(5), marker, label="marker='{0}'".format(marker))
plt.legend(numpoints=1)
plt.xlim(0, 1.8);
1
2
3
4
5
6

png

# 4.4.2 用plt.scatter绘制散点图

面对大型数据集时,使用 plt.plot 比 plt.scatter 方法好。

%matplotlib inline
import matplotlib.pyplot as plt
plt.style.use('seaborn-whitegrid')
import numpy as np
1
2
3
4
rng = np.random.RandomState(0)
x = rng.randn(100)
y = rng.randn(100)
colors = rng.rand(100)
sizes = 1000 * rng.rand(100)

plt.scatter(x, y, c=colors, s=sizes, alpha=0.3, cmap='viridis')
plt.colorbar()
# show color scale
1
2
3
4
5
6
7
8
9

png

# 4.5 误差线

# 4.5.1 基本误差线

plt.errorbar() 的 xerr、yerr 设置误差线,fmt 设置误差线外观,ecolor 设置误差线颜色,建议将误差线的颜色设置比数据点颜色浅一点。
1
%matplotlib inline
import matplotlib.pyplot as plt
plt.style.use('seaborn-whitegrid')
import numpy as np

x = np.linspace(0, 10, 50)
dy = 0.8
y = np.sin(x) + dy * np.random.randn(50)

# 绘制误差线
plt.errorbar(x, y, yerr=dy, fmt='.k', ecolor='lightgray');
1
2
3
4
5
6
7
8
9
10
11

png

# 4.5.2 连续误差

fill_between() 设置填充区域,实现连续误差的标注,填充区域为 y1~y2 之间

matplotlib.pyplot.fill_between(x, y1, y2=0, where=None, interpolate=False, step=None, *, data=None, **kwargs)[source]
1
2
3
x = np.linspace(0, 5 * np.pi, 1000)

y1 = np.sin(x)
y2 = np.sin(2 * x)

plt.plot(x, y1, c="g")
plt.plot(x, y2, c='r')

# 将两函数间区域填充成浅灰色
plt.fill_between(
    x, y1, y2, facecolor="lightgray")
1
2
3
4
5
6
7
8
9
10
11

png

# 4.6 密度图与等高线图

# 绘制等高线图
plt.contour()

# 绘制带有填充色的等高线图
plt.contourf()

# 显示图形
plt.imshow()
1
2
3
4
5
6
7
8
def f(x, y):
    return np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)
1
2
x = np.linspace(0, 5, 50)
y = np.linspace(0, 5, 40)

X, Y = np.meshgrid(x, y)
Z = f(X, Y)
1
2
3
4
5
plt.contour(X, Y, Z, colors='black');
1

png

plt.contour(X, Y, Z, 20, cmap='RdGy');
plt.colorbar();
1
2

png

# 4.7 频次直方图

# 4.7.1 一维频次直方图

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('seaborn-white')

data = np.random.randn(1000)
1
2
3
4
5
6
plt.hist(data);
1

png

# 4.7.2 二维频次直方图

mean = [0, 0]
cov = [[1, 1], [1, 2]]
x, y = np.random.multivariate_normal(mean, cov, 10000).T
1
2
3
plt.hist2d(x, y, bins=30, cmap='Blues')
cb = plt.colorbar()
cb.set_label('counts in bin')
1
2
3

png

counts, xedges, yedges = np.histogram2d(x, y, bins=30)
1
plt.hexbin(x, y, gridsize=30, cmap='Blues')
cb = plt.colorbar(label='count in bin')
1
2

png

# 4.8 图例

plt.legend() 创建图例
1
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('seaborn-white')
1
2
3
4
x = np.linspace(0, 10, 1000)
fig, ax = plt.subplots()
ax.plot(x, np.sin(x), '-b', label='Sine')
ax.plot(x, np.cos(x), '--r', label='Cosine')
ax.axis('equal')
leg = ax.legend();
1
2
3
4
5
6

png

# 4.9 颜色条

plt.colorbar() 显示颜色条
1
import matplotlib.pyplot as plt
plt.style.use('classic')
1
2
x = np.linspace(0, 10, 1000)
I = np.sin(x) * np.cos(x[:, np.newaxis])

plt.imshow(I)
plt.colorbar();
1
2
3
4
5

png

speckles = (np.random.random(I.shape) < 0.01)
I[speckles] = np.random.normal(0, 3, np.count_nonzero(speckles))

plt.figure(figsize=(10, 3.5))

plt.subplot(1, 2, 1)
plt.imshow(I, cmap='RdBu')
plt.colorbar()

plt.subplot(1, 2, 2)
plt.imshow(I, cmap='RdBu')
plt.colorbar(extend='both')
plt.clim(-1, 1);
1
2
3
4
5
6
7
8
9
10
11
12
13

png

plt.imshow(I, cmap=plt.cm.get_cmap('Blues', 6))
plt.colorbar()
plt.clim(-1, 1);
1
2
3

png

# 4.10 多子图

# 4.10.1 plt.axes手动创建子图

# 创建一个标准的坐标轴,填满整张图,左下角原点为0,右上角为1
plt.axes([bottom, left, width, height])

# 添加子图
fig = plt.figure()
fig.add_axes([bottom, left, width, height])
1
2
3
4
5
6
ax1 = plt.axes()  # standard axes
ax2 = plt.axes([0.65, 0.65, 0.2, 0.2])
1
2

png

fig = plt.figure()
ax1 = fig.add_axes([0.1, 0.5, 0.8, 0.4],
                   xticklabels=[], ylim=(-1.2, 1.2))
ax2 = fig.add_axes([0.1, 0.1, 0.8, 0.4],
                   ylim=(-1.2, 1.2))

x = np.linspace(0, 10)
ax1.plot(np.sin(x))
ax2.plot(np.cos(x));
1
2
3
4
5
6
7
8
9

png

# 4.10.2 plt.subplot简易网格子图(推荐)

# 创建 row x col 的网格子图,索引从1开始,从左上角到右下角依次增大
plt.subplot(row, col, i)
    
# 共享坐标轴
plt.subplots(row, col, sharex="col", sharey="row")

# 为每个 subplots 子图添加标题
subplots 创建后的 axes
ax = axes.ravel()
ax.title.set_text(title)

更复杂的布局参见官方文档。
1
2
3
4
5
6
7
8
9
10
11
12
# 简易网格子图
for i in range(1, 7):
    plt.subplot(2, 3, i)
    plt.text(0.5, 0.5, str((2, 3, i)), fontsize=18, ha='center')
1
2
3
4

png

# 共享坐标轴的网格子图
fig, ax = plt.subplots(2, 3, sharex='col', sharey='row')
1
2

png

# 为每个子图添加标题
fig, axes = plt.subplots(2, 3, sharex='col', sharey='row')
ax = axes.ravel() # 必要步骤

for i in range(2*3):
    ax[i].title.set_text(str((2, 3, i)))
1
2
3
4
5
6

png

# 4.11 文字与注释

# 文字
plt.text(x, y, s) 或 ax.text(x, y, s)

# 箭头与注释
plt.annotate(s, xy)
1
2
3
4
5
fig, ax = plt.subplots()

x = np.linspace(0, 20, 1000)
ax.plot(x, np.cos(x))
ax.axis('equal')

ax.annotate(
    'local maximum',
    xy=(6.28, 1),
    xytext=(10, 4),
    arrowprops=dict(facecolor='black', shrink=0.05))

ax.annotate(
    'local minimum',
    xy=(5 * np.pi, -1),
    xytext=(2, -6),
    arrowprops=dict(
        arrowstyle="->", connectionstyle="angle3,angleA=0,angleB=-90"))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

png

# 4.12 自定义坐标轴刻度

# 隐藏坐标轴刻度
ax = plt.axes()
ax.xaxis.set_major_formatter(plt.NullFormatter())
ax.yaxis.set_major_locator(plt.NullLocator())

更复杂的布局参见官方文档。
1
2
3
4
5
6
ax = plt.axes()
ax.plot(np.random.rand(50))

ax.yaxis.set_major_locator(plt.NullLocator())
ax.xaxis.set_major_formatter(plt.NullFormatter())
1
2
3
4
5

png

# 4.13 配置文件与样式表

# 4.13.2 默认文件

# 每次运行时加载的rc配置文件
plt.rcParams
1
2
# 示例
from matplotlib import cycler
colors = cycler('color',
                ['#EE6666', '#3388BB', '#9988DD',
                 '#EECC55', '#88BB44', '#FFBBBB'])
plt.rc('axes', facecolor='#E6E6E6', edgecolor='none',
       axisbelow=True, grid=True, prop_cycle=colors)
plt.rc('grid', color='w', linestyle='solid')
plt.rc('xtick', direction='out', color='gray')
plt.rc('ytick', direction='out', color='gray')
plt.rc('patch', edgecolor='#E6E6E6')
plt.rc('lines', linewidth=2)
1
2
3
4
5
6
7
8
9
10
11
12
plt.rcParams;
1

# 4.13.3 样式表

# 查看所有可用风格
plt.style.available

# 全文改变风格为 stylename
plt.style.use('stylename')

# 临时改变风格
with plt.style.context('stylename'):
    make_a_plot()
    
# 修改风格为 IPython_default
plt.rcParams.update(IPython_default);
1
2
3
4
5
6
7
8
9
10
11
12
# 查看前五个可用的风格
plt.style.available[:5]
1
2
['seaborn-dark',
 'seaborn-darkgrid',
 'seaborn-ticks',
 'fivethirtyeight',
 'seaborn-whitegrid']
import matplotlib.pyplot as plt
plt.style.use('classic')
import numpy as np

%matplotlib inline
1
2
3
4
5
def hist_and_lines():
    np.random.seed(0)
    fig, ax = plt.subplots(1, 2, figsize=(11, 4))
    ax[0].hist(np.random.randn(1000))
    for i in range(3):
        ax[1].plot(np.random.rand(10))
    ax[1].legend(['a', 'b', 'c'], loc='lower left')
1
2
3
4
5
6
7
hist_and_lines()
1

png

with plt.style.context('fivethirtyeight'):
    hist_and_lines()
1
2

png

with plt.style.context('ggplot'):
    hist_and_lines()
1
2

png

# 4.14 3D图

from mpl_toolkits import mplot3d
1
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
1
2
3
fig = plt.figure()
ax = plt.axes(projection='3d')
1
2

png

ax = plt.axes(projection='3d')

# Data for a three-dimensional line
zline = np.linspace(0, 15, 1000)
xline = np.sin(zline)
yline = np.cos(zline)
ax.plot3D(xline, yline, zline, 'gray')

# Data for three-dimensional scattered points
zdata = 15 * np.random.random(100)
xdata = np.sin(zdata) + 0.1 * np.random.randn(100)
ydata = np.cos(zdata) + 0.1 * np.random.randn(100)
ax.scatter3D(xdata, ydata, zdata, c=zdata, cmap='Greens');
1
2
3
4
5
6
7
8
9
10
11
12
13

png

# 4.15 用basemap可视化地理数据

# 解决错误 KeyError:'PROJ_LIB'
import os
import conda

conda_file_dir = conda.__file__
conda_dir = conda_file_dir.split('lib')[0]
proj_lib = os.path.join(os.path.join(conda_dir, 'share'), 'proj')
os.environ["PROJ_LIB"] = proj_lib
proj_lib
1
2
3
4
5
6
7
8
9
'/Users/nice/anaconda3/share/proj'
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
1
2
3
4
plt.figure(figsize=(8, 8))
m = Basemap(projection='ortho', resolution=None, lat_0=50, lon_0=-100)
m.bluemarble(scale=0.5);
1
2
3
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).

png

# 4.16 使用seaborn做数据可视化

matplotlib 三宗罪:

  1. matplotlib2.0 之前版本的默认配置样式不能满足用户
  2. matplotlib 的 API 比较底层,绘图需要大量代码
  3. 由于 matplotlib 比 pandas 早十几年,因此对 pandas 的 DataFrame 支持不好

seaborn 基于 matplotlib 的基础之上,解决了上述的三宗罪。

import seaborn as sns

iris = sns.load_dataset("iris")
iris.head()
1
2
3
4
sepal_length sepal_width petal_length petal_width species
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa
sns.pairplot(iris, hue='species', height=2.5);
1

png


<完>

上次更新时间: 2020/3/13 下午12:44:00