Bootstrap

Python绘图库:Matplotlib入门教程

9fe553a7f398bae30756b4fd804068be.gif

在后台回复【阅读书籍】

即可获取python相关电子书~

Hi,我是山月。

pandas教程里,我们提到过Matplotlib

它是一个非常强大的绘图库,能很轻松地将数据图形化,并且提供多样化的输出格式。

因此,今天我们就来看看它吧。

官网:https://matplotlib.org/3.2.2/contents.html

安装:pip install matplotlib

01

基础教程

导入库:

import matplotlib.pyplot as plt

1、常见术语

现在,让我们仔细的了解下 Matplotlib 图形的组成部分:

74fe824610c515c54b4115125f31aed2.png

1、Figure

整个图形。

Figure跟踪所有子 Axes、少量“特殊的”artists(标题、图形图例等)和画布。

一个图形可以包含任意数量的Axes,但通常至少有一个。

创建新图形的最简单方法是使用 pyplot:

import matplotlib.pyplot as plt # 导入库

fig = plt.figure()  # 没有轴的空图形
# fig, ax = plt.subplots()  # 单轴图形
# fig, axs = plt.subplots(2, 2)  # 具有2x2网格轴的图形

plt.show()  # 显示图表

效果:

2bc9410d70ced7bd21aed1e19da43992.png

2、Axes

你可以理解它为“a plot”,即一个图形上的数据点。

一个给定的图形可以包含多个 Axes,但一个给定的 Axes 对象只能在一个图形中。

Axes 包含两个(或在 3D 的情况下为三个)Axis 对象,它们负责数据限制。

数据限制可以通过 axes.Axes.set_xlim()和 axes.Axes.set_ylim() 方法。

每个Axes都有一个标题(通过 set_title() 设置)、一个 x 标签(通过 set_xlabel() 设置)和一个通过 set_ylabel() 设置的 y 标签

3、Axis

类似number-line的对象,即我们日常说的坐标轴

它们负责设置图形限制并生成刻度(轴上的标记)和刻度标签(标记刻度的字符串)。

刻度的位置由 Locator 对象确定,刻度标签字符串由 Formatter 格式化。


4、Artist

基本上,你在图上看到的所有东西都是Artist(甚至是 Figure、Axes和Axis对象)。

它也包括 Text 对象、Line2D 对象、collections对象、Patch 对象......。

渲染图形时,所有的Artist会被绘制到画布上。其中大多数Artist会被绑在轴上,这些Artist不能被多个轴共享,也不能从一个轴移动到另一个轴。

2、示例

Matplotlib 在图形上绘制数据图表,每个图形都可以包含一个或多个轴。

使用轴创建图形的最简单方法是使用 pyplot.subplots,然后使用 Axes.plot 在轴上绘制一些数据:

fig, ax = plt.subplots()  # 创建包含单个轴的图形。
ax.plot([1, 2, 3, 4], [1, 4, 2, 3])  # 在轴上绘制一些数据

但是对于 Axes 绘图方法,matplotlib.pyplot 模块中有一个相应的函数可以在“当前”轴上执行该绘图,如果它们尚不存在,则会创建该轴(及其父图形)。

所以前面的例子可以更简短地写成:

plt.plot([1, 2, 3, 4], [1, 4, 2, 3])

一个完整的图形绘制:

import matplotlib.pyplot as plt # 导入库

plt.plot([1, 2, 3, 4], [1, 4, 2, 3])    # 绘制图表

'''
相当于:
fig, ax = plt.subplots()  # 创建包含单个轴的图形。
ax.plot([1, 2, 3, 4], [1, 4, 2, 3])  # 在轴上绘制一些数据
'''

plt.show()  # 显示图表

结果:

72ed69b05afabbfb429a898835d44460.png

3、绘图函数的输入类型

所有绘图函数都需要 numpy.array 或 numpy.ma.masked_array 作为输入。

像 pandas 数据对象和 numpy.matrix 这样的“array-like”类可能不会按预期工作。所以最好在绘图之前将它们转换为 numpy.array 对象。

例如,要转换 pandas.DataFrame:

import pandas as pd
import numpy as np

a = pd.DataFrame(np.random.rand(4,5), columns = list('abcde'))
a_asarray = a.values
print(a)
print(a_asarray)
'''
          a         b         c         d         e
0  0.729035  0.885588  0.788884  0.203032  0.017212
1  0.734990  0.876627  0.462654  0.195555  0.821925
2  0.120534  0.345574  0.344897  0.829917  0.530056
3  0.419646  0.829288  0.852949  0.792325  0.793304

[[0.7290354  0.88558822 0.78888396 0.20303208 0.01721166] 
 [0.73499041 0.87662712 0.46265373 0.19555481 0.82192482] 
 [0.12053363 0.34557439 0.3448967  0.82991718 0.53005552] 
 [0.41964625 0.82928794 0.85294882 0.7923253  0.79330375]]
'''

转换 numpy.matrix:

import pandas as pd
import numpy as np

b = np.matrix([[1, 2], [3, 4]])
b_asarray = np.asarray(b)
print(b)
print(b_asarray)
'''
[[1 2] 
 [3 4]]
 
[[1 2] 
 [3 4]]
'''

4、object-oriented接口和pyplot接口

如上所述,有两种使用 Matplotlib 的方法:

  • 创建图形和轴,并在它们上调用方法(“面向对象 (OO) ”)。

  • 依靠 pyplot 自动创建和管理图形和坐标轴,并使用 pyplot 函数进行绘图。

使用OO方法:

import matplotlib.pyplot as plt
import numpy as np

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

# 注意,即使在OO样式中,我们也使用`.pyplot.figure`创建图形
fig, ax = plt.subplots()  # 创建一个图形和一个轴。

# 在轴上绘制一些数据
ax.plot(x, x, label='linear')  
ax.plot(x, x**2, label='quadratic')  
ax.plot(x, x**3, label='cubic') 

ax.set_xlabel('x label')  # 添加x轴标签
ax.set_ylabel('y label')  # 添加y轴标签
ax.set_title("Simple Plot")  # 添加标题
ax.legend()  # 添加图例

plt.show()  # 显示图表

pyplot 方法:

import matplotlib.pyplot as plt
import numpy as np

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

# 注意,即使在OO样式中,我们也使用`.pyplot.figure`创建图形
fig, ax = plt.subplots()  # 创建一个图形和一个轴。

# 在轴上绘制一些数据
ax.plot(x, x, label='linear')  
ax.plot(x, x**2, label='quadratic')  
ax.plot(x, x**3, label='cubic') 

ax.set_xlabel('x label')  # 添加x轴标签
ax.set_ylabel('y label')  # 添加y轴标签
ax.set_title("Simple Plot")  # 添加标题
ax.legend()  # 添加图例

plt.show()  # 显示图表

效果:

1169f30d5dd219de135b26fdab20cda1.png

通常,人们会发现自己一遍又一遍地绘制相同的图,只是使用了不同的数据集,因此可以编写专门的函数来进行绘图。

函数类似于:

def my_plotter(ax, data1, data2, param_dict):
    """
    生成图形的辅助函数

    参数
    ----------
    ax : Axes
        要绘制的Axes

    data1 : array
       x轴数据

    data2 : array
       y轴数据

    param_dict : dict
       要传递给ax.plot的关键字参数字典

    返回
    -------
    out : list
        新增的artists列表
    """
    out = ax.plot(data1, data2, **param_dict)
    return out

然后你可以运用它:

import matplotlib.pyplot as plt
import numpy as np

def my_plotter(ax, data1, data2, param_dict):
    out = ax.plot(data1, data2, **param_dict)
    return out

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

plt.show()  # 显示图表

效果:

480033a38fa1d9d7cda025faae89600f.png

如果你想有 2 个子图:

import matplotlib.pyplot as plt
import numpy as np

def my_plotter(ax, data1, data2, param_dict):
    out = ax.plot(data1, data2, **param_dict)
    return out

data1, data2, data3, data4 = np.random.randn(4, 100)

fig, (ax1, ax2) = plt.subplots(1, 2)
my_plotter(ax1, data1, data2, {'marker': 'x'})
my_plotter(ax2, data3, data4, {'marker': 'o'})

plt.show()  # 显示图表

效果:

589a1f667eaaab20db7d71027a4b7bf4.png

5、简化

Matplotlib 提供了几种方法来大大减少渲染时间,但代价是你的绘图外观略有变化(到可设置的容差)。

1、线段简化

对于具有线段的绘图(例如典型的线图、多边形的轮廓等),渲染性能可以由 matplotlibrc 文件中的 path.simplify 和 path.simplify_threshold 参数控制。

path.simplify 参数是一个布尔值,指示线段是否被简化。

path.simplify_threshold 参数控制简化多少线段;更高的阈值导致更快的渲染。

你可以分别试试下面的例子:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

# 设置并创建要绘制的数据
y = np.random.rand(100000)
y[50000:] *= 2
y[np.logspace(1, np.log10(50000), 400).astype(int)] = -1
mpl.rcParams['path.simplify'] = True

mpl.rcParams['path.simplify_threshold'] = 0.0
# mpl.rcParams['path.simplify_threshold'] = 1.0 # 换成这个运行看看

plt.plot(y)
plt.show()

Matplotlib 默认为 1/9 的保守简化阈值。

如果要更改默认设置以使用不同的值,可以更改 matplotlibrc 文件。

2、标记简化

也可以简化标记,尽管不如线段稳健。

标记简化仅适用于 Line2D 对象(通过 markevery 属性)。

凡是传入Line2D构造参数的地方,比如matplotlib.pyplot.plot()和matplotlib.axes.Axes.plot(),都可以使用markevery参数:

plt.plot(x, y, markevery=10)

markevery 参数允许进行简单的二次采样,或尝试均匀间隔(沿 x 轴)采样。

02

pyplot教程

1、pyplot 简介

matplotlib.pyplot 是使 matplotlib 像 MATLAB 一样工作的命令样式函数的集合。

每个 pyplot 函数都会对图形进行一些更改,例如,创建图形、在图形中创建绘图区域、在绘图区域中绘制一些线、用标签装饰绘图等。

使用 pyplot 生成可视化非常快:

import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4])
plt.ylabel('some numbers')
plt.show()

效果:

d4ecc88351d2000240fb572ee1c87c3b.png

至于为什么 x 轴的范围是 0-3 而 y 轴的范围是 1-4。

那是因为如果你向 plot() 命令提供单个列表或数组,matplotlib 会假定它是一个 y 值序列,并自动为你生成 x 值。

而默认的 x 向量的长度与 y 相同,但从 0 开始,因此 x 数据为 [0, 1, 2, 3]。

plot() 是一个通用命令,可以接受任意数量的参数。例如:

import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4], [1, 4, 9, 16])
plt.show()

效果:

a8ceb87fe815bcba71cda229573c2617.png

对于每对 x、y 参数,都有一个可选的第三个参数,它是表示绘图颜色和线型的格式字符串。

格式字符串的字母和符号来自 MATLAB,你可以将颜色字符串与线型字符串连接起来。

默认格式字符串是“b-”,它是一条蓝色实线。

例如,要绘制红色圆圈,你可以:

import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4], [1, 4, 9, 16], 'ro')
plt.axis([0, 6, 0, 20])
plt.show()

效果:

4beab52132924614597e9a42921ed50a.png

注意:示例中的 axis() 命令采用 [xmin, xmax, ymin, ymax] 列表来指定x、y轴的范围。

下面的示例说明了使用数组在一个命令中绘制具有不同样式的多条线:

import matplotlib.pyplot as plt
import numpy as np

# 以200ms间隔均匀采样时间
t = np.arange(0., 5., 0.2)

# 红色虚线、蓝色正方形和绿色三角形
plt.plot(t, t, 'r--', t, t**2, 'bs', t, t**3, 'g^')
plt.show()

效果:

bb629a5f1ace128d74cc6c1ee70eb6f2.png

2、使用关键字字符串绘图

在某些情况下,数据格式允许你使用字符串访问特定变量。例如numpy.recarray 或 pandas.DataFrame。

Matplotlib 允许你为这样的对象提供 data 关键字参数,并使用与这些变量对应的字符串生成图。

import matplotlib.pyplot as plt
import numpy as np

data = {'a': np.arange(50),
        'c': np.random.randint(0, 50, 50),
        'd': np.random.randn(50)}
data['b'] = data['a'] + 10 * np.random.randn(50)
data['d'] = np.abs(data['d']) * 100

plt.scatter('a', 'b', c='c', s='d', data=data)
plt.xlabel('entry a')
plt.ylabel('entry b')
plt.show()

效果:

7b317853cd04892531faf5d1eecaee0d.png

3、使用分类变量绘图

可以使用分类变量创建绘图。例如:

import matplotlib.pyplot as plt

names = ['group_a', 'group_b', 'group_c']
values = [1, 10, 100]

plt.figure(figsize=(9, 3))

plt.subplot(131)
plt.bar(names, values)
plt.subplot(132)
plt.scatter(names, values)
plt.subplot(133)
plt.plot(names, values)
plt.suptitle('Categorical Plotting')
plt.show()

效果:

323ed7e0654bd979da2f7b01484eb1f6.png

4、线属性

线条有许多可以设置的属性:线宽、虚线样式、反走样等。

可以通过以下几种方法来设置线属性:

1、使用关键字参数

import matplotlib.pyplot as plt

x=[1, 2, 3, 4]
plt.plot(x, linewidth=3.0)  # 设置线宽

plt.ylabel('some numbers')
plt.show()

效果:

4f053e5b747c7aea94ab3c259667703b.png

2、使用 Line2D 的setter 方法

plot 返回 Line2D 对象的列表。

import matplotlib.pyplot as plt

x = [1, 2, 3, 4]
y = [1, 4, 9, 16]

line, = plt.plot(x, y, '-')
line.set_antialiased(False) # 关闭antialiasing

print(line) # >>> Line2D(_child0)
plt.show()

效果:

107161aafa1af57816bf40c86e7c1982.png

要获取可设置属性的列表,可以使用一行或多行作为参数调用 setp() 函数:

import matplotlib.pyplot as plt

lines = plt.plot([1, 2, 3])
print(plt.setp(lines))

以下是可用的 Line2D 属性

5dbb08d721767d9ac1302883ca2bde10.png

3、使用 setp() 命令

可以使用 python 关键字参数或 MATLAB 样式的字符串/值对:

import matplotlib.pyplot as plt

x = [1, 2, 3, 4]
y = [1, 4, 9, 16]

lines = plt.plot(x, y)
# 使用关键字参数
plt.setp(lines, color='r', linewidth=2.0)
# 或者 MATLAB 字符串值对
# plt.setp(lines, 'color', 'r', 'linewidth', 2.0)

plt.show()

效果:

537c6226c1fbf4b3e0d38f3d714cf8b2.png

5、多个图形和轴

MATLAB 和 pyplot 具有当前图形和当前坐标区的概念,所有绘图命令都适用于当前轴。

函数 gca() 返回当前坐标区(matplotlib.axes.Axes 实例),gcf() 返回当前图形(matplotlib.figure.Figure 实例)。

下面是创建两个子图的脚本。

import matplotlib.pyplot as plt
import numpy as np

def f(t):
    return np.exp(-t) * np.cos(2*np.pi*t)

t1 = np.arange(0.0, 5.0, 0.1)
t2 = np.arange(0.0, 5.0, 0.02)

plt.figure()
plt.subplot(211) #subplot(211)指的是在一个2行1列共2个子图的图中,定位第1个图来进行操作。
plt.plot(t1, f(t1), 'bo', t2, f(t2), 'k')

plt.subplot(212)
plt.plot(t2, np.cos(2*np.pi*t2), 'r--')
plt.show()

效果:

6d44193203546263d073f2680404733b.png

此处的 figure() 命令是可选的,因为默认情况下会创建 figure(1),就像不手动指定任何轴时默认创建 subplot(111) 一样。

subplot() 命令指定 numrows、numcols、plot_number。

其中 plot_number 的范围从 1 到 numrows*numcols。

如果 numrows*numcols<10,则 subplot 命令中的逗号是可选的。

所以 subplot(211) 与 subplot(2, 1, 1) 相同。

如果你想手动放置轴,即不放在矩形网格上,可以使用 axes() 命令,该命令允许你将位置指定为轴([left, bottom, width, height]),其中所有值都是小数(0 到 1) 坐标。

你可以通过使用多个 figure() 调用以及不断增加的数字来创建多个图形。

当然,每个图形都可以包含你想要的任意数量的轴和子图:

import matplotlib.pyplot as plt
plt.figure(1)                # 第一个图形
plt.subplot(211)             # 第一个图形中的第1个子图
plt.plot([1, 2, 3])
plt.subplot(212)             # 第一个图形中的第2个子图
plt.plot([4, 5, 6])

plt.figure(2)                # 第二个图形
plt.plot([4, 5, 6])          # 创建默认子图,默认subplot(111)

plt.figure(1)                # 当前图形为figure 1; 由于subplot(212) 在211后面定义,所以当前子图为subplot(212)
plt.subplot(211)             # 定义当前子图为subplot(211) 
plt.title('Easy as 1, 2, 3') # 给211子图定义标题

plt.show()

效果:

71c136dd06840bd97aabfac67c47ac19.png

可以使用 clf() 清除当前图形,使用 cla() 清除当前坐标区。

如果你要制作大量图形,则需要注意一件事:图形所需的内存不会完全释放,直到用 close() 显式关闭图形。

所以删除对图形的所有引用、使用窗口管理器杀死图形出现在屏幕上的窗口都是不够的,因为 pyplot 维护内部引用,直到调用 close()。

5、文本处理

text() 命令可用于在任意位置添加文本,xlabel()、ylabel() 和 title() 用于在指定位置添加文本:

import matplotlib.pyplot as plt
import numpy as np

mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)

# 柱状图
n, bins, patches = plt.hist(x, 50, density=1, facecolor='g', alpha=0.75)

plt.xlabel('Smarts')
plt.ylabel('Probability')
plt.title('Histogram of IQ')
plt.text(60, .025, r'$\mu=100,\ \sigma=15$')
plt.axis([40, 160, 0, 0.03])
plt.grid(True)
plt.show()

效果:

86c4674760c84bbd97ff33658ddc162a.png

所有 text() 命令都返回一个 matplotlib.text.Text 实例。

你也可以通过将关键字参数传递给文本函数或使用 setp() 来自定义属性:

plt.xlabel('my data', fontsize=14, color='red')

效果:

52a66e41dfa1238e9dc19881ce77ab9e.png

1、在文本中使用数学表达式

matplotlib 接受任何文本表达式中的 TeX 方程表达式。

比如在标题中写表达式 σ = 15,你可以写一个用美元符号包围的 TeX 表达式:

plt.title(r'$\sigma_i=15$')

字符串前面的 r 很重要:它表示该字符串是一个原始字符串,而不是将反斜杠视为 python 转义。

matplotlib 有一个内置的 TeX 表达式解析器和布局引擎,并提供自己的数学字体。

有关详细信息,可以参阅:https://matplotlib.org/3.2.2/tutorials/index.html,在之后也会介绍。

因此,你可以跨平台使用数学文本,而无需安装 TeX。

2、注释文本

text() 命令的使用可以将文本放置在轴上的任意位置。

文本的一个常见用途是对绘图的某些特征进行注释,并且 annotate() 方法提供了帮助功能使注释变得容易。

在注释中,需要考虑两点:参数 xy 表示的被注释位置和文本 xytext 的位置,这两个参数都是 (x, y) 元组。

import matplotlib.pyplot as plt
import numpy as np

ax = plt.subplot(111)

t = np.arange(0.0, 5.0, 0.01)
s = np.cos(2*np.pi*t)
line, = plt.plot(t, s, lw=2)

plt.annotate('local max', xy=(2, 1), xytext=(3, 1.5),
             arrowprops=dict(facecolor='black', shrink=0.05),
             )
'''
local max:注释的内容
xy:箭头头的坐标
 xytext:注释内容的起始位置
arrowprops:设置箭头的一些属性,颜色、宽度等
'''
plt.ylim(-2, 2)
plt.show()

效果:

cad7cea8a4c645ea0c2e2f04fb73fc8f.png

6、对数轴

matplotlib.pyplot 不仅支持线性轴刻度,还支持对数刻度。如果数据跨越多个数量级,则通常使用此方法。

如:

import matplotlib.pyplot as plt
import numpy as np

# 固定随机状态以实现再现性
np.random.seed(19680801)

# 在开放区间(0,1)中生成一些数据
y = np.random.normal(loc=0.5, scale=0.4, size=1000)
y = y[(y > 0) & (y < 1)]
y.sort()
x = np.arange(len(y))

# 用不同的轴比例绘制图形
plt.figure()

# linear
plt.subplot(121)
plt.plot(x, y)
plt.yscale('linear')
plt.title('linear')
plt.grid(True)

# log
plt.subplot(122)
plt.plot(x, y)
plt.yscale('log')
plt.title('log')
plt.grid(True)

plt.show()

效果:

d1af2bf8d9c424013c059d8d6e200b64.png

03

图片处理

1、导入所需模块

import matplotlib.pyplot as plt
import matplotlib.image as mpimg

注意: Matplotlib 只支持 PNG 图像。

2、将图像数据导入 Numpy 数组

这是示例图像:

d590e049e16606dc6ccdf83943b9c336.png

它是一个 24 位 (R、G、B 各 8 位)的RGB PNG 图像。

当然,你可能遇到的其他类型的图像是 RGBA 图像,它允许透明度,或单通道灰度(亮度)图像。

img = mpimg.imread('数据.png')
print(img)

Matplotlib 已将每个通道的 8 位数据重新缩放为 0.0 到 1.0 之间的浮点数据,每个内部列表代表一个像素。

对于 RGB 图像,有 3 个值。由于它是黑白图像,因此 R、G 和 B 都相似。

对于 RGBA(其中 A 是 alpha 或透明度),每个内部列表有 4 个值,而简单的亮度图像只有一个值(因此只是一个 2-D 数组,而不是 3-D 数组)。

3、将 numpy 数组绘制为图像

在 Matplotlib 中,可以使用 imshow() 函数来渲染图像数据生成的numpy数组。

imgplot = plt.imshow(img)
1、将伪彩色方案应用于图像图

伪彩色仅与单通道、灰度、亮度图像相关。

我们目前有一个 RGB 图像,由于 它的R、G 和 B 都是相似的,我们可以只选择一个数据通道:

import matplotlib.pyplot as plt
import matplotlib.image as mpimg

img = mpimg.imread('数据.png')

#将伪彩色方案应用于图像图
lum_img = img[:, :, 0]
plt.imshow(lum_img)

plt.show()

效果:

7b850b863d1a47d1027976fa65931d32.png

如果想为图像添加亮度,可以使用默认的colormap(又名查找表,LUT),它的参数默认为 viridis。

plt.imshow(lum_img, cmap="hot") # 设为hot

效果:

faedb52a9b9bf504f6db5fbd2295f259.png

你还可以使用 set_cmap() 方法更改现有绘图对象的colormaps:

imgplot = plt.imshow(lum_img)
imgplot.set_cmap('nipy_spectral')

效果:

16f5c2888ae19ff5740e5284b067ef01.png

2、色标

了解颜色代表的价值是有帮助的。我们可以通过为图形添加一个颜色条来做到这一点:

import matplotlib.pyplot as plt
import matplotlib.image as mpimg

img = mpimg.imread('数据.png')
lum_img = img[:, :, 0]

imgplot = plt.imshow(lum_img)
plt.colorbar()

plt.show()

效果:

ba8c6f5a8abeaf47e4b4426517b10d13.png

3、检查特定数据范围

如果你希望增强图像的对比度,或扩大特定区域的对比度,同时可以牺牲掉一些变化不大或无关紧要的颜色细节,那你可以利用直方图。

使用 hist() 函数来创建图像数据的直方图:

import matplotlib.pyplot as plt
import matplotlib.image as mpimg

img = mpimg.imread('数据.png')
lum_img = img[:, :, 0]

plt.hist(lum_img.ravel(), bins=256, range=(0.0, 1.0), fc='k', ec='k')

plt.show()

效果:

e27e6a41d1d4f90bbd17d49e7c0e8687.png

可以发现,峰值在0.5-0.6附近,0.7以上就没什么数据了。

而通过将 clim 参数传递给 imshow ,或调用图像绘图对象的 set_clim() 方法可以裁剪峰值上方和/或下方的区域,以此来改变对比度

来看看对比示例吧:

import matplotlib.pyplot as plt
import matplotlib.image as mpimg

img = mpimg.imread('数据.png')
lum_img = img[:, :, 0]

fig = plt.figure()

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

a = fig.add_subplot(1, 2, 2)
imgplot = plt.imshow(lum_img, clim=(0.0, 0.7))
# 也可以:
# imgplot = plt.imshow(lum_img)
# imgplot.set_clim(0.0, 0.7)
a.set_title('After')
plt.colorbar(ticks=[0.1, 0.3, 0.5, 0.7], orientation='horizontal')

plt.show()

效果:

adf86a8a45214d5335575e1b7c7676b7.png

4、插值

插值是对原图像的像素重新分布,从而来改变像素数量的一种方法。

在这里我们需要用到Pillow 库:

import matplotlib.pyplot as plt
from PIL import Image

img = Image.open('数据.png')
img.thumbnail((64, 64), Image.ANTIALIAS)
imgplot = plt.imshow(img)

plt.show()

效果:

d0d8033875ffc7d8e1d9d29c5454b226.png

这里我们使用插值的默认值:bilinear(双线性插值),因为我们没有给 imshow() 任何插值参数。

最临近插值(nearest)

imgplot = plt.imshow(img, interpolation="nearest")

效果:

a8c09e0cb471bf401f73a77c5272c0f7.png

双三次插值(bicubic):

imgplot = plt.imshow(img, interpolation="bicubic")

效果:

b0fac50a9354cb8a70f2756afccb1ebf.png

04

完整实例

1、数据

生成条形图:

import numpy as np
import matplotlib.pyplot as plt

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)

fig, ax = plt.subplots()
ax.barh(group_names, group_data)
plt.show()

效果:

a3fd583d15cada79a56d40d8889584f0.png

2、设置样式

Matplotlib 中有许多样式,样式可以控制很多东西,比如颜色、线宽、背景等。

我们可以使用style查看样式列表

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

现在让我们重新制作上面的图:

plt.style.use('fivethirtyeight') #样式设置成fivethirtyeight
fig, ax = plt.subplots()
ax.barh(group_names, group_data)

效果:

eee50702fa81d024b8d6b553e431c447.png

3、自定义图形

现在我们已经有了一个基础的图形,我们可以对其进行微调,以便它可以打印。

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter

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)

plt.style.use('fivethirtyeight') # 设置样式
plt.rcParams.update({'figure.autolayout': True}) # 设置自动布局
fig, ax = plt.subplots(figsize=(8, 4)) #使用subplots() 函数调整图的大小,其中figsize值是:(宽度、高度),单位是英寸。
ax.barh(group_names, group_data)
labels = ax.get_xticklabels() # 访问x轴标签
plt.setp(labels, rotation=45, horizontalalignment='right') # 旋转x轴标签
ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
       title='Company Revenue') # 添加标签

plt.show()

效果:

3ba2d536414eb43ece6d2683b943b1b9.png

对于标签,我们也可以通过ticker.FuncFormatter以函数的形式来指定自定义格式:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter

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)

plt.style.use('fivethirtyeight') # 设置样式
plt.rcParams.update({'figure.autolayout': True}) # 设置自动布局
fig, ax = plt.subplots(figsize=(8, 4)) #使用subplots() 函数调整图的大小,其中figsize值是:(宽度、高度),单位是英寸。
ax.barh(group_names, group_data)
labels = ax.get_xticklabels() # 访问x轴标签
plt.setp(labels, rotation=45, horizontalalignment='right') # 旋转x轴标签
ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
       title='Company Revenue') # 添加标签

def currency(x, pos):
    if x >= 1e6:
        s = '${:1.1f}M'.format(x*1e-6)
    else:
        s = '${:1.0f}K'.format(x*1e-3)
    return s

formatter = FuncFormatter(currency)   
ax.xaxis.set_major_formatter(formatter)    

plt.show()

效果:

4f84baea4d7476f997dadbd43d9ff2f6.png

4、结合多个元素

我们只需要在轴对象上调用另一个绘图方法就可以在 axes.Axes 的同一个实例上绘制多个绘图元素:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter

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)

plt.style.use('fivethirtyeight') # 设置样式
plt.rcParams.update({'figure.autolayout': True}) # 设置自动布局
fig, ax = plt.subplots(figsize=(8, 4)) #使用subplots() 函数调整图的大小,其中figsize值是:(宽度、高度),单位是英寸。
ax.barh(group_names, group_data)
labels = ax.get_xticklabels() # 访问x轴标签
plt.setp(labels, rotation=45, horizontalalignment='right') # 旋转x轴标签
ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
       title='Company Revenue') # 添加标签

def currency(x, pos):
    if x >= 1e6:
        s = '${:1.1f}M'.format(x*1e-6)
    else:
        s = '${:1.0f}K'.format(x*1e-3)
    return s

formatter = FuncFormatter(currency)   
ax.xaxis.set_major_formatter(formatter)    

# 添加一条垂直线
ax.axvline(group_mean, ls='--', color='r')

# 注释
for group in [3, 5, 8]:
    ax.text(145000, group, "New Company", fontsize=10,
            verticalalignment="center")

# 把标题向上移动
ax.title.set(y=1.05)

ax.set_xticks([0, 25e3, 50e3, 75e3, 100e3, 125e3])
fig.subplots_adjust(right=.1)

plt.show()

效果:

d00241398bf29b6b83e84b290813a5c2.png

5、保存图形

我们可以在 Matplotlib 中保存许多文件格式:

import matplotlib.pyplot as plt
fig, ax = plt.subplots()
print(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'}
'''

然后我们可以使用 figure.Figure.savefig() 将图形保存。

几个说明:

  • transparent=True: 如果格式支持,则使保存的图形的背景透明。

  • dpi=80 :控制输出的分辨率(每平方英寸的点数)。

  • bbox_inches="tight" :使图形的边界适合我们的图形。

# 保存图形
 fig.savefig('山月.png', transparent=False, dpi=80, bbox_inches="tight")

今天的内容就到这里啦~

60a7d61ef9c252480c05fca992bd4d6c.png

END

dc6b1699e62b6243dc68d734778a80bd.gif

您的“点赞”、“在看”和 “分享”是我们产出的动力。

;