logo

Matplotlib

wangzf / 2022-09-23


目录

一个 Plot 的生命周期

import numpy as np
import matplotlib.pyplot as plt

print(plt.style.available)
plt.style.use("fivethirtyeight")
plt.rcParams.update({
    "figure.autolayout": True,
})


# data
data = {
    'Barton LLC': 109438.50,
    'Frami, Hills and Schmidt': 103569.59,
    'Fritsch, Russel and Anderson': 112214.71,
    'Jerde-Hilpert': 112591.43,
    'Keeling LLC': 100934.30,
    'Koepp Ltd': 103660.54,
    'Kulas Inc': 137351.96,
    'Trantow-Barrows': 123381.38,
    'White-Trantow': 135841.99,
    'Will LLC': 104437.60
}
group_data = list(data.values())
group_names = list(data.keys())
group_mean = np.mean(group_data)


# plot
def currency(x, pos):
    """
    The two arguments are the value and tick position

    Args:
    x ([type]): [description]
    pos ([type]): [description]
    """
    if x >= 1e6:
        s = "${:1.1f}M".format(x * 1e-6)
    else:
        s = "${:1.0f}K".format(x * 1e-3)
    return s

fig, ax = plt.subplots(figsize = (8, 4))
# bar
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation = 45, horizontalalignment = "right")
# vertical line
ax.axvline(group_mean, ls = "--", color = "r")
# group text
for group in [3, 5, 8]:
    ax.text(
        145000, 
        group, 
        "New Company", 
        fontsize = 10, 
        verticalalignment = "center"
    )
# 标题设置
ax.title.set(y = 1.05)
# 设置X轴限制、X轴标签、Y轴标签、主标题
ax.set(
    xlim = [-10000, 140000], 
    xlabel = "Total Revenue", 
    ylabel = "Company", 
    title = "Company Revenue"
)
# 设置X轴主刻度标签格式
ax.xaxis.set_major_formatter(currency)
# 设置X轴主刻度标签
ax.set_xticks([0, 25e3, 50e3, 75e3, 100e3, 125e3])
# 微调fig
fig.subplots_adjust(right = 0.1)
# 图片保存
print(fig.canvas.get_supported_filetypes())
fig.savefig("sale.png", transparent = False, dpi = 80, bbox_inches = "tight")
plt.show()

快速开始

def quick_start():
    import numpy as np
    import matplotlib as mpl
    import matplotlib.pyplot as plt

    X = np.linspace(0, 2 * np.pi, 100)
    Y = np.cos(X)

    fig, ax = plt.subplots()
    ax.plot(X, Y, color = "green")

    fig.savefig(
        os.path.join(
            os.path.dirname(__file__), 
            "images/figure.png"
        )
    )
    fig.show()

quick_start()

一张统计图的结构

图形 API

import matplotlib.pyplot as plt

fig, ax = plt.subplots()

Figure

Figure class

fig = plt.fiure()			  # an empty figure with no Axes
fig, ax = plt.subplots()      # a figure with a single Axes
fig, ax = plt.subplots(2, 2) # a figure with a 2x2 grid of Axes

Axes class

Axis class

Artist class

Subplots layout

Subplots layout,子图布局

API

subplots

def subplots_layout():
    fig, ax = plt.subplots(3, 3)
    fig.show()

img

gridsepc

inset_axes

make_axes_locatable

Matplotlib 开发环境

Python Script

plt.show()

IPython shell

IPython Notebook

%matploblib inline

Matplotlib 编程接口

Matplotlib 的文档和示例同时使用 OO 和 pyplot 方法(它们同样强大), 可以随意使用其中任何一种(但是,最好选择其中之一并坚持使用,而不是混合使用它们)。 通常,建议将 pyplot 限制为交互式绘图(例如,在 Jupyter 笔记本中), 并且更喜欢 OO 风格的非交互式绘图(在旨在作为更大项目的一部分重用的函数和脚本中)。

下面是两个简单的示例:

fig = plt.figure()
# or plt.figure()
ax = plt.axes()
plt.plot(
    [1, 2, 3, 4],
    [1, 4, 2, 3]
);
fig = plt.figure()
ax = plt.axes()
ax.plot(
    [1, 2, 3, 4],
    [1, 4, 2, 3]
);
fig, ax = plt.subplots()
ax.plot(
    [1, 2, 3, 4],
    [1, 4, 2, 3]
);

pyplot 接口

MatLab 风格接口

pyplot 是使 Matplotlib 像 MATLAB 一样工作的函数集合。每个 pyplot 函数都会对图形进行一些更改: 例如,创建图形、在图形中创建绘图区域、在绘图区域中绘制一些线条、用标签装饰绘图等。 在 pyplot 函数调用中保留各种状态,以便跟踪当前图形(figure)和绘图区域(plotting area)等内容,并且绘图函数指向当前轴(axes)

API

示例

# 图形
fig = plt.figure(num = 2, figsize = (8, 8))
# 坐标轴
# ax = plt.axes()

plt.subplot(211)
plt.plot(x, np.sin(x), label = "sin")
plt.xlabel("x label")
plt.ylabel("y label")
plt.title("Simple Plot")
plt.legend()

plt.subplot(212)
plt.plot(x, np.cos(x), label = "cos")
plt.xlabel("x label")
plt.ylabel("y label")
plt.title("Simple Plot")
plt.legend()
plt.show()

fig.savefig();
plt.gcf() # 获取当前图形(figure)
plt.gca() # 获取当前坐标轴(axes)

OOP 接口

API

示例

# data
x = np.linspace(0, 2, 100)

# plot
fig, ax = plt.subplots(1, 3, figsize = (18, 5), sharey = True)
ax[0].plot(x, x, label = "linear")
ax[0].plot(x, x**2, label = "quadratic")
ax[0].plot(x, x**3, label = "cubic")
ax[0].set_xlabel("x label")
ax[0].set_ylabel("y label")
ax[0].set_title("linear Plot")
ax[0].legend()

ax[1].plot(x, x, label = "linear")
ax[1].plot(x, x**2, label = "quadratic")
ax[1].plot(x, x**3, label = "cubic")
ax[1].set_xlabel("x label")
ax[1].set_ylabel("y label")
ax[1].set_title("quadratic Plot")
ax[1].legend()

ax[2].plot(x, x, label = "linear")
ax[2].plot(x, x**2, label = "quadratic")
ax[2].plot(x, x**3, label = "cubic")
ax[2].set_xlabel("x label")
ax[2].set_ylabel("y label")
ax[2].set_title("cubic Plot")
ax[2].legend();

GUI 应用程序中嵌入 Matplotlib

最佳实践

def my_plotter(ax, data1, data2, param_dict):
    """
    A helper function to make a graph

    Parameters
    ----------
    ax : Axes
        The axes to draw to

    data1 : array
       The x data

    data2 : array
       The y data

    param_dict : dict
       Dictionary of keyword arguments to pass to ax.plot

    Returns
    -------
    out : list
        list of artists added
    """
       out = ax.plot(data1, data2, **param_dict)
    return out
# data
data1, data2, data3, data4 = np.random.randn(4, 100)
# plot
fig, ax = plt.subplots(1, 1)
my_plotter(ax, data1, data2, {"marker": "x"})

![image-20211201235123195](/Users/zfwang/Library/Application Support/typora-user-images/image-20211201235123195.png)

# data
data1, data2, data3, data4 = np.random.randn(4, 100)
# plot
fig, ax = plt.subplots(1, 1)
my_plotter(ax, data1, data2, {"marker": "x"})
my_plotter(ax, data3, data4, {"marker": "o"})

![image-20211201235141268](/Users/zfwang/Library/Application Support/typora-user-images/image-20211201235141268.png)

Matplotlib 个性化

优先级: rcParams > style sheets > matplotlibrc file

rcParams

rc: runtime configuration

API

配置选项

rc = dict(mpl.rcParams)
rc_table = pd.DataFrame({
    "param": rc.keys(),
    "value": rc.values(),
})
# rc_table

全局设置

from cycler import cycler

# lines
mpl.rcParams["lines.linewidth"] = 2
mpl.rcParams["lines.linestyle"] = "--"
mpl.rc("lines", linewidth = 4, linestyle = "--")
# axes
mpl.rcParams["axes.porp_cycle"] = cycler(color = ["r", "g", "b", "y"])

临时设置

with mpl.rc_context({"lines.linewidth": 2, "lines.linestyle": ":"}):
    plt.plot(data)

@mpl.rc_context({"lines.linewidth": 3, "lines.linestyle": "-"})
def plotting_function():
    plt.plot(data)

style sheets

API

所有样式

print(plt.style.available)
['Solarize_Light2',
 '_classic_test_patch',
 '_mpl-gallery',
 '_mpl-gallery-nogrid',
 'bmh',
 'classic',
 'dark_background',
 'fast',
 'fivethirtyeight',
 'ggplot',
 'grayscale',
 'seaborn-v0_8',
 'seaborn-v0_8-bright',
 'seaborn-v0_8-colorblind',
 'seaborn-v0_8-dark',
 'seaborn-v0_8-dark-palette',
 'seaborn-v0_8-darkgrid',
 'seaborn-v0_8-deep',
 'seaborn-v0_8-muted',
 'seaborn-v0_8-notebook',
 'seaborn-v0_8-paper',
 'seaborn-v0_8-pastel',
 'seaborn-v0_8-poster',
 'seaborn-v0_8-talk',
 'seaborn-v0_8-ticks',
 'seaborn-v0_8-white',
 'seaborn-v0_8-whitegrid',
 'tableau-colorblind10']

全局样式

plt.style.use("ggplot")
plt.style.use("./images/presentation.mplstyle")
plt.style.use(["dark_background", "presentation"])

临时样式

with plt.style.context("dark_background"):
    plt.plot(data)

matplotlibrc file

matplotlibrc 文件的位置:

查看当前加载的 matplotlibrc 文件的位置

mpl.matploblib_fname()
'D:\\software\\miniconda3\\envs\\pysci\\lib\\site-packages\\matplotlib\\mpl-data\\matplotlibrc'

Matplotlib 图形保存

图像文件格式

savefig() 里面,保存的图片文件格式就是文件的扩展名。 Matplotlib 支持许多图形格式,可以通过 canvas 对象的方法查看系统支持的文件格式

fig = plt.figure()
fig.canvas.get_supported_filetypes()
{'eps': 'Encapsulated Postscript',
 'jpg': 'Joint Photographic Experts Group',
 'jpeg': 'Joint Photographic Experts Group',
 'pdf': 'Portable Document Format',
 'pgf': 'PGF code for LaTeX',
 'png': 'Portable Network Graphics',
 'ps': 'Postscript',
 'raw': 'Raw RGBA bitmap',
 'rgba': 'Raw RGBA bitmap',
 'svg': 'Scalable Vector Graphics',
 'svgz': 'Scalable Vector Graphics',
 'tif': 'Tagged Image File Format',
 'tiff': 'Tagged Image File Format',
 'webp': 'WebP Image Format'}

保存

fig.savefig("my_figure.png")

展示

from IPython.display import Image

Image("my_figure.png")

基本图形

plot

plot([X], Y, [fmt], color, marker, linestyle)

scatter

散点图

scatter(X, Y, [s]izes, [c]olors, markers, alpha, cmap)

bar

bar[h](x, height, width, bottom, align, color)

imshow

imshow(Z, cmap, interpolation, extent, origin)

contour

contour[f]([X], [Y], Z, levels, colors, extent, origin)

pcolormesh

pcolormesh([X], [Y], Z, vmin, vmax, cmap)

quiver

quiver([X], [Y], U, V, C, units, angles)

pie

pie(Z, explode, labels, colors, raidus)

text

text(x, y, text, va, ha, size, weight, transform)

fill

fill[_between][x](X, Y1, Y2, color, where)

高级图形

step

step(X, Y, [fmt], color, marker, where)

boxplot

boxplot(X, notch, sym, bootstrap, widths)

errorbar

errorbar(X, Y, xerr, yerr, fmt)

示例:

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

# plot
fig = plt.figure()
plt.errorbar(
    x, y, 
    yerr = dy, 
    xerr = dx
    fmt = ".k", 
    ecolor = "lightgray", 
    elinewidth = 3, 
    capsize = 0
)

hist

hist(X, bins, range, density, weights)

violinplot

violinplot(D, positions, widths, vert)

barbs

barbs([X], [Y], U, V, C, length, pivot, sizes)

eventplot

eventplot(positions, orientation, lineoffsets)

hexbin

hexbin(X, Y, C, gridsize, bins)

Color, Line, Marker

Color

Sigle Color

常用单色:

character color
'b' blue
'g' green
'r' red
'c' cyan
'm' magenta
'y' yellow
'k' black
'w' white
# data
x = np.linspace(0, 10, 1000)

# plot
fig, ax = plt.subplots()
ax.plot(x, x + 0, color='blue', label = "blue")  # 标准颜色名称
ax.plot(x, x + 1, color='g', label = "g")  # 缩写颜色代码(rgbcmyk)
ax.plot(x, x + 2, color='0.75', label = "0.75")  # 范围在0~1的灰度值
ax.plot(x, x + 3, color='#FFDD44', label = "#FFDD44")  # 十六进制(RRGGBB,00~FF)
ax.plot(x, x + 4, color=(1.0,0.2,0.3), label = "(1.0,0.2,0.3)")  # RGB元组,范围在0~1
ax.plot(x, x + 5, color='chartreuse', label = "chartreuse")  # HTML颜色名称
ax.legend(loc = "best");

img

Colormaps

img

Line

linestyle 或者 ls

character description
'-' solid line style 实线
'--' dashed line style 实点线
'-.' dash-dot line style 虚线
':' dotted line style 点划线
# data
x = np.linspace(0, 10, 1000)

# plot
fig, ax = plt.figure(), plt.axes()
plt.plot(x, x + 0, linestyle='solid', label = "solid")
plt.plot(x, x + 1, linestyle='dashed', label = "dashed")
plt.plot(x, x + 2, linestyle='dashdot', label = "dashdot")
plt.plot(x, x + 3, linestyle='dotted', label = "dotted")
plt.plot(x, x + 4, linestyle='-', label = "-") # 实线
plt.plot(x, x + 5, linestyle='--', label = "--") # 虚线
plt.plot(x, x + 6, linestyle='-.', label = "-.") # 点划线
plt.plot(x, x + 7, linestyle=':', label = ":") # 实点线
plt.legend(loc = "best");

img

Marker

marker:

character description
'.' point marker
',' pixel marker
'o' circle marker
'v' triangle_down marker
'^' triangle_up marker
'<' triangle_left marker
'>' triangle_right marker
'1' tri_down marker
'2' tri_up marker
'3' tri_left marker
'4' tri_right marker
'8' octagon marker
's' square marker
'p' pentagon marker
'P' plus (filled) marker
'*' star marker
'h' hexagon1 marker
'H' hexagon2 marker
'+' plus marker
'x' x marker
'X' x (filled) marker
'D' diamond marker
'd' thin_diamond marker
'|' vline marker
'_' hline marker

示例:

fig, ax = plt.subplots(figsize = (12, 12))
rng = np.random.RandomState(0)
for marker in [".", ",", "o", "v", "^", "<", ">", 
               "1", "2", "3", "4", "8", "s", "p", "P", 
               "*", "h", "H", "x", "X", "+", "d", "D", 
               "|", "_"]:
    plt.plot(rng.rand(5), rng.rand(5), marker, label = f"marker={marker}")
    plt.legend(numpoints = 1)
    plt.xlim(0, 1.8)

marker 参数:

# data
x = np.linspace(0, 10, 30)
y = np.sin(x)

# plot
fig, ax = plt.subplots(figsize = (5, 5))
plt.plot(
    x, y, "-p", color = "gray", linewidth = 4,
    markersize = 15,
    markerfacecolor = "white",
    markeredgecolor = "gray",
    markeredgewidth = 2,
)

Color 加 Line 和 Marker

使用示例:

# data
x = np.linspace(0, 10, 1000)

# plot
fig, ax = plt.figure(), plt.axes()
plt.plot(x, x + 0, '-g') # 绿色实线
plt.plot(x, x + 1, '--c') # 青色虚线
plt.plot(x, x + 2, '-.k') # 黑色点划线
plt.plot(x, x + 3, ':r'); # 红色实点线
plt.plot(x, x + 4, 'or');
plt.plot(x, x + 5, '^k');
plt.legend(loc = "best");

Scales

ax.set_[xy]scale(scale, ...)

Projections

subplot(..., projection = p)

Tick locators

from matplotlib import ticker

ax.[xy]axis.set_[minor|major]_locator(locator)

locator:

Tick formatters

from matplotlib import ticker

ax.[xy]axis.set_[minor|major]_formatter(formatter)

formatter:

Ornaments

Event handling

import matplotlib.pyplot as plt

fig, ax = plt.subplots()

def on_click(event):
    print(event)

fig.canvas.mpl_connect("button_press_event", on_click)

Animation

import matplotlib.animation as mpla

T = np.linspace(0, 2 * np.pi, 100)
S = np.sin(T)
line, = plt.plot(T, S)

def animate(i):
    line.set_ydata(np.sin(T + i / 50))

anim = mpla.FuncAnimation(plt.gcf(), animate, interval = 5)
plt.show()

Quick reminder

import matplotlib.pyplot as plt

fig, ax = plt.subplots()

ax.grid()
ax.set_[xy]lim(vmin, vmax)
ax.set_[xy]label(label)
ax.set_[xy]ticks(ticks, [labels])
ax.set_[xy]ticklabels(labels)
ax.set_title(title)
ax.tick_params(width = 10, ...)
ax.set_axis_[on|off]()

fig.suptitle(title)

fig.tight_layout()

plt.gcf(), plt.gca()

mpl.rc("axes", linewidth = 1, ...)

[fig|ax].patch.set_alpha(0)

text = r"$frac{-e^{i\pi}}{2^n}"

函数输入格式

# pandas.DataFrame 转换
pandas_dataframe = pandas.DataFrame()
array_inputs = pandas_datarframe.values

# numpy.matrix 转换
numpy_matrix = numpy.matrix([1, 2], [3, 4])
array_inputs = numpy.asarray(numpy_matrix)

Image

import matplotlib.image as mpimg

将 image 数据转换为 Numpy array

../../_images/stinkbug.png

img = mpimg.imread("stinkbug.png")
print(img)
print(img.shape)

[[[0.40784314 0.40784314 0.40784314]
  [0.40784314 0.40784314 0.40784314]
  [0.40784314 0.40784314 0.40784314]
  ...
  [0.42745098 0.42745098 0.42745098]
  [0.42745098 0.42745098 0.42745098]
  [0.42745098 0.42745098 0.42745098]]

 [[0.4117647  0.4117647  0.4117647 ]
  [0.4117647  0.4117647  0.4117647 ]
  [0.4117647  0.4117647  0.4117647 ]
  ...
  [0.42745098 0.42745098 0.42745098]
  [0.42745098 0.42745098 0.42745098]
  [0.42745098 0.42745098 0.42745098]]

 [[0.41960785 0.41960785 0.41960785]
  [0.41568628 0.41568628 0.41568628]
  [0.41568628 0.41568628 0.41568628]
  ...
  [0.43137255 0.43137255 0.43137255]
  [0.43137255 0.43137255 0.43137255]
  [0.43137255 0.43137255 0.43137255]]

 ...

 [[0.4392157  0.4392157  0.4392157 ]
  [0.43529412 0.43529412 0.43529412]
  [0.43137255 0.43137255 0.43137255]
  ...
  [0.45490196 0.45490196 0.45490196]
  [0.4509804  0.4509804  0.4509804 ]
  [0.4509804  0.4509804  0.4509804 ]]

 [[0.44313726 0.44313726 0.44313726]
  [0.44313726 0.44313726 0.44313726]
  [0.4392157  0.4392157  0.4392157 ]
  ...
  [0.4509804  0.4509804  0.4509804 ]
  [0.44705883 0.44705883 0.44705883]
  [0.44705883 0.44705883 0.44705883]]

 [[0.44313726 0.44313726 0.44313726]
  [0.4509804  0.4509804  0.4509804 ]
  [0.4509804  0.4509804  0.4509804 ]
  ...
  [0.44705883 0.44705883 0.44705883]
  [0.44705883 0.44705883 0.44705883]
  [0.44313726 0.44313726 0.44313726]]]

(375, 500, 3)

将 Numpy array 绘制成图片

imgplot = plt.imshow(img)

![image-20211204001730928](/Users/zfwang/Library/Application Support/typora-user-images/image-20211204001730928.png)

将伪彩色方案应用于图像

lum_img = img[:, :, 0]
plt.imshow(lum_img)

![image-20211204003701542](/Users/zfwang/Library/Application Support/typora-user-images/image-20211204003701542.png)

lum_img = img[:, : 0]
plt.imshow(lum_img, cmap = "hot")

![image-20211204003910446](/Users/zfwang/Library/Application Support/typora-user-images/image-20211204003910446.png)

lum_img = img[:, :, 0]
imgplot = plt.imshow(lum_img)
imgplot.set_cmap("nipy_spectral")

![image-20211204004118731](/Users/zfwang/Library/Application Support/typora-user-images/image-20211204004118731.png)

色标参考

lum_img = img[:, : 0]
imgplot = plt.imshow(lum_img)
plt.colorbar()

![image-20211204004308940](/Users/zfwang/Library/Application Support/typora-user-images/image-20211204004308940.png)

检查特定数据范围

lum_img = img[:, :, 0]
plt.hist(lum_img.ravel(), bins = 256, range(0.0, 1.0), fc = "k", ec = "k")

![image-20211204005900327](/Users/zfwang/Library/Application Support/typora-user-images/image-20211204005900327.png)

# 调增上限,有效放大直方图中的一部分
lum_img = img[:, :, 0]
imgplot = plt.imshow(lum_img, clim = (0.0, 0.7))

![image-20211204010057096](/Users/zfwang/Library/Application Support/typora-user-images/image-20211204010057096.png)

lum_img = img[:, :, 0]

fig = plt.figure()

ax = fig.add_subplot(1, 2, 1)
imgplot = plt.imshow(lum_img)
ax.set_title('Before')
plt.colorbar(ticks=[0.1, 0.3, 0.5, 0.7], orientation='horizontal')

ax = fig.add_subplot(1, 2, 2)
imgplot = plt.imshow(lum_img)
imgplot.set_clim(0.0, 0.7)
ax.set_title('After')
plt.colorbar(ticks=[0.1, 0.3, 0.5, 0.7], orientation='horizontal')

![image-20211204011743914](/Users/zfwang/Library/Application Support/typora-user-images/image-20211204011743914.png)

数组插值

from PIL import Image

img = Image.open("stinkbug.png")
img.thumbnail((64, 64), Image.ANTIALIAS) # resizes image in-replace
imgplot = plt.imshow(img)

![image-20211204011041795](/Users/zfwang/Library/Application Support/typora-user-images/image-20211204011041795.png)

from PIL import Image

img = Image.open("stinkbug.png")
img.thumbnail((64, 64), Image.ANTIALIAS) # resizes image in-replace
imgplot = plt.imshow(img, interpolation = "nearest")

![image-20211204011222797](/Users/zfwang/Library/Application Support/typora-user-images/image-20211204011222797.png)

from PIL import Image

img = Image.open("stinkbug.png")
img.thumbnail((64, 64), Image.ANTIALIAS) # resizes image in-replace
imgplot = plt.imshow(img, interpolation = "bicubic")

![image-20211204011514588](/Users/zfwang/Library/Application Support/typora-user-images/image-20211204011514588.png)

资料