Matplotlib绘图
user guide: https://matplotlib.org/users/index.html
官方教程:https://www.matplotlib.org.cn/tutorials/
其它教程:https://www.runoob.com/w3cnote/matplotlib-tutorial.html
Matplotlib参数工作逻辑:
figure是放置图表的容器,axes是坐标系,默认情况下,一张纸(figure)被 1个图表(axes)占满
matplotlib里有三个概念:轴-axis,刻度-tick,标签-label,通常我们的操作都是基于axes,因为我们在操作整个图表
图表主要元素的函数说明
函数 | 核心参数 | 功能 |
---|---|---|
figure() | figsize:图表尺寸,dpi:分辨率 | 设置图像的大小和分辨率 |
title() | str:图表名称,fontdict:文本格式/字体大小/类型 | 设置标题 |
xlabel(),ylabel() | xlabel:X轴名,ylabel:Y轴名 | 设置X/Y轴的标题 |
axis(),xlim(),ylim() | xmin,xmax或ymin,ymax | 设置X/Y轴的范围 |
xticks(),yticks() | ticks:刻度数值,labels:刻度名称,fontdict | 设置X/Y轴的刻度 |
grid() | b:有无网格,which:主次网格,axis:X/Y轴网格线,color,linestyle,linewidth,alpha:透明度 | 设置X/Y轴的主要和次要网格线 |
legend() | loc:位置,edgecolor,facecolor,fontsize | 控制图例显示 |
常见图表类型
ID | 图表类型 | 函数 | 核心参数 |
---|---|---|---|
1 | 折线图 | plot() | |
2 | 散点图/汽泡图 | scatter() | |
3 | 柱形图/堆积柱形图 | bar() | |
4 | 条形图/规程条形图 | barh | |
5 | 面积图 | fill_between | |
6 | 堆积面积图/量化波形图 | stackplot | |
7 | 饼图 | pie() | |
8 | 误差棒 | errorbar | |
9 | 统计直方图 | hist() | |
10 | 箱形图 | boxplot() | |
11 | 垂直X轴直线/垂直Y轴直线 | axhline(),axvline() | |
12 | 垂直X轴矩形/垂直Y轴矩形 | axhspan(),axvspan() | |
13 | 指定位置文本 | text() | |
14 | 指定数据点标注 | annotate() |
plt.setp(对象)查看对象可设置的属性 --一个好用的入门方法
plt.setp本身也是一种快速批量修改属性的方法,可以查看axes的众多属性
plt.setp(axes)
plt.setp(axes)
adjustable: {'box', 'datalim'}
agg_filter: a filter function, which takes a (m, n, 3) float array and a dpi value, and returns a (m, n, 3) array
alpha: float or None
anchor: 2-tuple of floats or {'C', 'SW', 'S', 'SE', ...}
animated: bool
aspect: {'auto'} or num
autoscale_on: bool
autoscalex_on: bool
autoscaley_on: bool
axes_locator: Callable[[Axes, Renderer], Bbox]
axisbelow: bool or 'line'
box_aspect: None, or a number
clip_box: `.Bbox`
clip_on: bool
clip_path: Patch or (Path, Transform) or None
contains: unknown
facecolor or fc: color
figure: `.Figure`
frame_on: bool
gid: str
in_layout: bool
label: object
navigate: bool
navigate_mode: unknown
path_effects: `.AbstractPathEffect`
picker: None or bool or callable
position: [left, bottom, width, height] or `~matplotlib.transforms.Bbox`
prop_cycle: unknown
rasterization_zorder: float or None
rasterized: bool or None
sketch_params: (scale: float, length: float, randomness: float)
snap: bool or None
subplotspec: unknown
title: str
transform: `.Transform`
url: str
visible: bool
xbound: unknown
xlabel: str
xlim: (bottom: float, top: float)
xmargin: float greater than -0.5
xscale: {"linear", "log", "symlog", "logit", ...}
xticklabels: unknown
xticks: unknown
ybound: unknown
ylabel: str
ylim: (bottom: float, top: float)
ymargin: float greater than -0.5
yscale: {"linear", "log", "symlog", "logit", ...}
yticklabels: unknown
yticks: unknown
zorder: float
以上属性,获取的方式是:axes.get_xticklabels(),即使用“前缀+下划线+属性名”来调用。
也可以再查看它的子属性,如plt.setp(axes.get_xticklabels())或plt.setp(axes.get_xticklabels()[0]),但是不是每个子属性都可以用plt.setp()查看下去的。
再比如:
plt.setp(fig)
plt.setp(fig)
agg_filter: a filter function, which takes a (m, n, 3) float array and a dpi value, and returns a (m, n, 3) array
alpha: float or None
animated: bool
canvas: FigureCanvas
clip_box: `.Bbox`
clip_on: bool
clip_path: Patch or (Path, Transform) or None
constrained_layout: bool or dict or None
constrained_layout_pads: unknown
contains: unknown
dpi: float
edgecolor: color
facecolor: color
figheight: float
figure: `.Figure`
fig float
frameon: bool
gid: str
in_layout: bool
label: object
path_effects: `.AbstractPathEffect`
picker: None or bool or callable
rasterized: bool or None
size_inches: (float, float) or float
sketch_params: (scale: float, length: float, randomness: float)
snap: bool or None
tight_layout: bool or dict with keys "pad", "w_pad", "h_pad", "rect" or None
transform: `.Transform`
url: str
visible: bool
zorder: float
以上的这些属性,我们会在后面用到。
面向对象设计,意味着图表上能看到的对象都有一个对象代表它,matplotlib的灵活在于对细节的控制。
查看自定义对象的属性(非常重要!)
通过查看自定义对象的属性, 可以方便修改,举个简单的例子:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
df = pd.DataFrame({'year':[1565,1570,1575,1580,1585],'wheat':[41,45,42,49,41.5],'wages':[5,5.05,5.08,5.12,5.15]})
df.year = df.year.astype(str)
fig,axes = plt.subplots()
fig.set_figwidth(20)
fig.set_figheight(10)
bar = axes.bar(df.year,df.wheat)
这里定义了 bar, 它是一个 <BarContainer object of 5 artists>
为了修改它, 我们可以用plt.setp(bar)来查看它的属性。
plt.setp(bar)
agg_filter: a filter function, which takes a (m, n, 3) float array and a dpi value, and returns a (m, n, 3) array
alpha: float or None
animated: bool
antialiased or aa: unknown
bounds: (left, bottom, width, height)
capstyle: {'butt', 'round', 'projecting'}
clip_box: `.Bbox`
clip_on: bool
clip_path: Patch or (Path, Transform) or None
color: color
contains: unknown
edgecolor or ec: color or None or 'auto'
facecolor or fc: color or None
figure: `.Figure`
fill: bool
gid: str
hatch: {'/', '\', '|', '-', '+', 'x', 'o', 'O', '.', '*'}
height: unknown
in_layout: bool
joinstyle: {'miter', 'round', 'bevel'}
label: object
linestyle or ls: {'-', '--', '-.', ':', '', (offset, on-off-seq), ...}
linewidth or lw: float or None
path_effects: `.AbstractPathEffect`
picker: None or bool or callable
rasterized: bool or None
sketch_params: (scale: float, length: float, randomness: float)
snap: bool or None
transform: `.Transform`
url: str
visible: bool
unknown
x: unknown
xy: (float, float)
y: unknown
zorder: float
知道了它的属性,我们就能方便的对它进行操作。具体内容见“设置颜色”一节。
设置画布的大小
第一种方法:直接在subplots里用figsize=(x,y)指定:
fig,axes = plt.subplots(figsize=(20,10))
第二种方法:用plt.setp方式找到属性 figwidth, figheight
fig.set_figwidth(20)
fig.set_figheight(10)
以上两种方法等效。
设置颜色
接查看自定义对象的属性(非常重要!)的例子:
min_bar = df.wheat.idxmin() #idxmin()是对一列求最小,返回其索引值 ,而非数据本身
max_bar = df.wheat.idxmax()
bar[min_bar].set_color('orange')
bar[max_bar].set_color('red')
设置图表标题和水平线
axes.set(title = 'wheat each year', xlabel = 'year',ylabel='wheat')
axes.axhline(df.wheat.mean(),c='red',ls='--')
设置图表字体大小
plt.rcParams.update({'axes.titlesize':45,'axes.labelsize':25})
plt.rcParams.update({'font.size':20})
绘图实例
1.折线图 plot()详解
绘制plot图-- 极简起步 plt.plot(x,y)
import numpy as np
from matplotlib import pyplot as plt
x = np.arange(1,11)
y = 2 * x + 5
plt.title("Matplotlib demo")
plt.xlabel("x axis caption")
plt.ylabel("y axis caption")
plt.plot(x,y)
plt.show()
绘制plot --讲解设定
import numpy as np
from matplotlib import pyplot as plt
# 创建一个 8 * 6 点(point)的图,并设置分辨率为 80
fig = plt.figure(figsize=(10,5),dpi=80)
# 创建一个新的 1 * 1 的子图,接下来的图样绘制在其中的第 1 块(也是唯一的一块)
plt.subplot(1,1,1)
X = np.linspace(-np.pi, np.pi, 256,endpoint=True)
C,S = np.cos(X), np.sin(X)
# 绘制余弦曲线,使用蓝色的、连续的、宽度为 1 (像素)的线条
plt.plot(X, C, color="blue", linewidth=1.0, linestyle="-")
# 绘制正弦曲线,使用绿色的、连续的、宽度为 1 (像素)的线条
plt.plot(X, S, color="green", linewidth=1.0, linestyle="-")
# 设置横轴的上下限
plt.xlim(-4.0,4.0)
# 设置横轴记号
plt.xticks(np.linspace(-4,4,9,endpoint=True))
# 设置纵轴的上下限
plt.ylim(-1.0,1.0)
# 设置纵轴记号
plt.yticks(np.linspace(-1,1,5,endpoint=True))
# 以分辨率 72 来保存图片
# savefig("exercice_2.png",dpi=72)
# 在屏幕上显示
plt.show()
绘制plot --进阶: 设定线型/颜色/粗细/标签
import numpy as np
from matplotlib import pyplot as plt
fig = plt.figure(figsize=(10,5))
data = np.linspace(0,10,100)
#在指定的间隔范围内返回均匀间隔的数字。在[start, stop]范围内计算,返回num个(默认为50)均匀间隔的样本。
#参考:https://blog.csdn.net/benben_dog/article/details/85446452
plt.plot(data, np.sin(data), c='r',ls='--',lw=4,label="label name")
plt.xlabel('I am X Axis')
plt.ylabel('I am Y Axis')
plt.title("data desc")
plt.legend()
plt.show()
绘制plot -- 另一个角度出发,设置风格并保存
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
# Data for plotting
t = np.arange(0.0, 2.0, 0.01)
s = 1 + np.sin(2 * np.pi * t)
fig, ax = plt.subplots()
ax.plot(t, s)
ax.set(xlabel='time (s)', ylabel='voltage (mV)',
title='About as simple as it gets, folks')
ax.grid()
fig.savefig("test.png")
plt.show()
绘制plot --双曲线图 plt.plot(x,y)
import numpy as np
from matplotlib import pyplot as plt
fig = plt.figure(figsize=(10,5))
data = np.linspace(0,10,100)
plt.plot(data, np.sin(data), 'r-o', label="test legend A")
plt.plot(data, np.cos(data), 'g--', label="test legend B")
# 两个线也可以这样写: plt.plot(x_line1, y_line2, 'r', x_line2, y_line2, 'b')
# 尝试取消下面注释运行(这种方式, 貌似图例不方便分开配置)
# plt.plot(data, np.sin(data), 'r-o', data, np.cos(data), 'g--', label="A")
plt.xlabel('I am X Axis')
plt.ylabel('I am Y Axis')
plt.title("data desc")
plt.legend()
plt.show()
绘制多个plot --双图 plt.plot(x,y)
import numpy as np
from matplotlib import pyplot as plt
x1 = np.linspace(0.0, 5.0)
y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)
x2 = np.linspace(0.0, 2.0)
y2 = np.cos(2 * np.pi * x2)
plt.subplot(2, 1, 1)
plt.plot(x1, y1, 'o-')
plt.title('A tale of 2 subplots')
plt.ylabel('Damped oscillation')
plt.subplot(2, 1, 2)
plt.plot(x2, y2, '.-')
plt.xlabel('time (s)')
plt.ylabel('Undamped')
plt.show()
绘制多个plot --双图(for循环写)
import numpy as np
import matplotlib.pyplot as plt
plt.figure(1) # 创建图表1
plt.figure(2) # 创建图表2
ax1 = plt.subplot(211) # 在图表2中创建子图1
ax2 = plt.subplot(212) # 在图表2中创建子图2
x = np.linspace(0, 3, 100)
for i in range(5):
plt.figure(1) # 选择图表1
plt.plot(x, np.exp(i*x/3))
plt.sca(ax1) # 选择图表2的子图1
plt.plot(x, np.sin(i*x))
plt.sca(ax2) # 选择图表2的子图2
plt.plot(x, np.cos(i*x))
plt.show()
2 散点图/汽泡图 scatter()
绘制scatter(x,y)入门
import numpy as np
from matplotlib import pyplot as plt
x = np.linspace(0.05,10,1000)
y = np.random.rand(1000)
plt.scatter(x,y,label='scatter figure')
plt.legend()
plt.show()
Matplotlib图表的导出
plt.savefig()函数可以将Matplotlib图表导出不同的格式,包括pdf,png,jpg,svg等,注意:plt和word共同支持的格式有:jpg,jpeg,png,svg,tif,tiff
其中,只有svg矢量图保存到word后不会模糊,其它格式的文件保存后模糊都十分严重。
例:导出到pdf的代码如下:
plt.savefig('filename.pdf',format='pdf')
plt.show() # plt.savefig()必须 在plt.show()之前调用
如果要保持图片的清晰度,可以使用:
plt.savefig('test.png',dpi=600)
plt.show()
Matplotlib中文支持问题
Matplotlib 默认情况不支持中文,我们可以使用以下简单的方法来解决。
1.从本机COPY一个字体到py文件的目录中
并且在python语句中加入下一句:
zhfont1 = matplotlib.font_manager.FontProperties(fname="Deng.ttf") #这里引用的是'等线'中文字体
然后就可以在title或lable中引用了。效果如下:
import numpy as np
from matplotlib import pyplot as plt
import matplotlib
# fname 为你指定的字体库路径
zhfont1 = matplotlib.font_manager.FontProperties(fname="Deng.ttf")
x = np.arange(1,11)
y = 2 * x + 5
plt.title("菜鸟教程 - 测试", fontproperties=zhfont1)
# fontproperties 设置中文显示,fontsize 设置字体大小
plt.xlabel("x 轴", fontproperties=zhfont1)
plt.ylabel("y 轴", fontproperties=zhfont1)
plt.plot(x,y)
plt.show()
如果不知道把字体文件放在哪里,可以运行下一句命令,直接打开当前py文件所在的目录
import os
working_path = os.getcwd()
os.system("explorer.exe %s" % working_path) #打开py文件所在的目录
2.不更新任何字体,直接使用命令:
import numpy as np
from matplotlib import pyplot as plt
import matplotlib as mpl
mpl.rcParams['font.sans-serif'] = ['KaiTi']
mpl.rcParams['font.serif'] = ['KaiTi']
mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题,或者转换负号为字符串
x = np.arange(1,11)
y = 2 * x + 5
plt.title("菜鸟教程 - 测试")
plt.xlabel("x 轴")
plt.ylabel("y 轴")
plt.plot(x,y)
plt.show()
其中,第三句mpl.rcParams['axes.unicode_minus'] = False是用来排除 ‘RuntimeWarning: Glyph 8722 missing from current font.’错误提示的
上面那三句写成这样也是可以的:
plt.rcParams['font.sans-serif'] = ['KaiTi']
plt.rcParams['font.serif'] = ['KaiTi']
plt.rcParams['axes.unicode_minus'] = False
3.使用网上的思源黑体,思源黑体是 Adobe 与 Google 推出的一款开源字体。
官网:https://source.typekit.com/source-han-serif/cn/
GitHub 地址:https://github.com/adobe-fonts/source-han-sans/tree/release/OTF/SimplifiedChinese
打开链接后,在里面选一个就好了:
你也可以在网盘下载: https://pan.baidu.com/s/14cRhgYvvYotVIFkRVd71fQ 提取码: e15r。
可以下载个 OTF 字体,比如 SourceHanSansSC-Bold.otf,将该文件文件放在当前执行的代码文件中
Pandas DataFrame绘图
对于普通的二维表,如果df只有2列,可以用下面的命令直接画折线图:
df.plot()
参考网站
matplotlib中文网
https://www.matplotlib.org.cn/
《Python数据可视化之matplotlib实践》 作者:刘大成 中国工信出版社