由于篇幅限制,将文章分为两部分,这是第二部分。
点击链接《 Matplotlib 绘图原理(一)》可直达第一部分。
- 线条样式
- 在图上添加文本
- 示例:节假日对美国出生率的影响
- 添加箭头和文字说明
- 误差线
- 加网格线
- 保存图片
- 移动坐标轴
- 使得轴刻度落在坐标轴上
- 多子图
- plt.subplot()
- plt.subplotsf
- fg.add_subplot()
- 常用图形
- 折线图
- 散点图
- 直方图
- 饼图
- 箱线图
- 画一个填充好颜色的形状
线条样式
plot()
绘图接口中 mark
参数
点标记名称 | 标记 |
---|---|
点(point marker) | . |
像素点(pixel marker) | , |
圆形(circle marker) | o |
正方形(square marker) | s’ |
三角形(向下,上,左,右) | v, ^, <, > |
三角星(向下,上,左,右) | 1, 2, 3, 4 |
五边星(pentagon marker) | p |
星型(star marker) | * |
1 号六角形(hexagon1 marker) | h |
2 号六角形(hexagon2 marker) | H |
号标记(plus marker) |
|
x 号标记(x marker) | x |
菱形(diamond marker) | D |
窄型菱形(thin_diamond marker) | d |
垂直线形(vline marker) | | |
水平线形(hline marker) | _ |
示例
代码语言:javascript复制x = np.linspace(-5, 5, 50)
# 创建画布
plt.figure(figsize=(8, 5))
plt.plot(x, x, color='r', marker='o', markersize=1, alpha=0.3)
plt.plot(x, np.sin(x), color='g', marker='p', markersize=5, alpha=0.6)
plt.plot(x, np.cos(x), color = 'y', marker='v', markersize=7, alpha=0.9)
plt.legend(["$y=x$", "$y=sin(x)$", "$y=cos(x)$"]);
在图上添加文本
常用参数方式: plt.text(x, y, 要添加的内容)
- x: 位置的横坐标
- y: 位置的纵坐标
- 要添加的内容字符串,同样接受 LaTex 语法
示例:节假日对美国出生率的影响
数据来源:关注《数据 STUDIO》,回复【birth】获取数据。
数据预处理
代码语言:javascript复制%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib as mpl
plt.style.use('seaborn-whitegrid')
import numpy as np
import pandas as pd
births = pd.read_csv('birth.csv')
# 计算生日的百分位数
quartiles = np.percentile(births['births'], [25, 50, 75])
# 标准化IQR是一个结果变异性的量度,
# 它是稳健统计技术处理中用于表示数据分散程度的一个量,
# 它等于四分位间距(IQR)乘以因子0.741 3,其与一个标准偏差相类似。
mu, sig = quartiles[1], 0.74 * (quartiles[2] - quartiles[0])
# 使用布尔表达式查询数据帧的列,剔除离群值
births = births.query('(births > @mu - 5 * @sig) & (births < @mu 5 * @sig)')
births['day'] = births['day'].astype(int)
births.index = pd.to_datetime(10000 * births.year 100 * births.month births.day
, format='%Y%m%d')
births_by_date = births.pivot_table('births'
,[births.index.month, births.index.day])
births_by_date.index = [pd.datetime(2020
, month
, day) for (month, day) in births_by_date.index]
绘图
代码语言:javascript复制fig, ax = plt.subplots(figsize=(12, 4))
births_by_date.plot(ax=ax)
# 在图上增加文字标签
style = dict(size=10, color='gray')
ax.text('2020-1-1', 3950, "New Year's Day", **style)
ax.text('2020-7-4', 4250, "Independence Day", ha='center', **style)
ax.text('2020-9-4', 4850, "Labor Day", ha='center', **style)
ax.text('2020-10-31', 4600, "Halloween", ha='right', **style)
ax.text('2020-11-25', 4450, "Thanksgiving", ha='center', **style)
ax.text('2020-12-25', 3850, "Christmas ", ha='right', **style)
# 设置坐标轴标题
ax.set(title='USA births by day of year (1969-1988)',
ylabel='average daily births')
# 设置x轴刻度值,让月份居中显示
ax.xaxis.set_major_locator(mpl.dates.MonthLocator())
ax.xaxis.set_minor_locator(mpl.dates.MonthLocator(bymonthday=15))
ax.xaxis.set_major_formatter(plt.NullFormatter())
ax.xaxis.set_minor_formatter(mpl.dates.DateFormatter('%h'));
结果
添加箭头和文字说明
代码语言:javascript复制plt.annotate(text, (x, y), (textx, texty), arrowprops=dict(arrowstyle="->", color='r'))
常用参数
- text: 进行说明的文本
- (x, y): 要进行说明的点的横纵坐标
- (textx, texty): 说明的文本的要放的位置的横纵坐标
- arrowprops=dict(arrowstyle="->")
示例
代码语言:javascript复制fig, ax = plt.subplots(figsize=(12, 4))
births_by_date.plot(ax=ax)
# 在图上增加箭头标签
ax.annotate("New Year's Day", xy=('2020-1-1', 4100), xycoords='data',
xytext=(50, -30), textcoords='offset points',
arrowprops=dict(arrowstyle="->",
connectionstyle="arc3,rad=-0.2"))
ax.annotate("Independence Day", xy=('2020-7-4', 4250), xycoords='data',
bbox=dict(boxstyle="round", fc="none", ec="gray"),
xytext=(10, -40), textcoords='offset points', ha='center',
arrowprops=dict(arrowstyle="->"))
ax.annotate('Labor Day', xy=('2020-9-4', 4850), xycoords='data', ha='center',
xytext=(0, -20), textcoords='offset points')
ax.annotate('', xy=('2020-9-1', 4850), xytext=('2020-9-7', 4850),
xycoords='data', textcoords='data',
arrowprops={'arrowstyle': '|-|,widthA=0.2,widthB=0.2', })
ax.annotate('Halloween', xy=('2020-10-31', 4600), xycoords='data',
xytext=(-80, -40), textcoords='offset points',
arrowprops=dict(arrowstyle="fancy",
fc="0.6", ec="none",
connectionstyle="angle3,angleA=0,angleB=-90"))
ax.annotate('Thanksgiving', xy=('2020-11-25', 4500), xycoords='data',
xytext=(-120, -60), textcoords='offset points',
bbox=dict(boxstyle="round4,pad=.5", fc="0.9"),
arrowprops=dict(arrowstyle="->",
connectionstyle="angle,angleA=0,angleB=80,rad=20"))
ax.annotate('Christmas', xy=('2020-12-25', 3850), xycoords='data',
xytext=(-30, 0), textcoords='offset points',
size=13, ha='right', va="center",
bbox=dict(boxstyle="round", alpha=0.1),
arrowprops=dict(arrowstyle="wedge,tail_width=0.5", alpha=0.1));
# 设置坐标轴标题
ax.set(title='USA births by day of year (1969-1988)',
ylabel='average daily births')
# 设置x轴刻度值,让月份居中显示
ax.xaxis.set_major_locator(mpl.dates.MonthLocator())
ax.xaxis.set_minor_locator(mpl.dates.MonthLocator(bymonthday=15))
ax.xaxis.set_major_formatter(plt.NullFormatter())
ax.xaxis.set_minor_formatter(mpl.dates.DateFormatter('%h'));
ax.set_ylim(3600, 5400);
关于箭头和注释风格的更多介绍与示例,可以在 Matplotlib 的画廊gallery[1]中看到,尤其推荐
误差线
对任何一种科学测量方法来说,准确地衡量数据误差都是无比重要的事情,甚至比数据本身还要重要。在数据可视化的结果中用图形将误差有效地显示出来,就可以提供更充分的信息。
代码语言:javascript复制x = np.linspace(0, 10, 50)
dy = 0.8
y = np.sin(x) dy * np.random.randn(50)
plt.figure(figsize=(8, 5))
plt.errorbar(x, y,
yerr=dy,
fmt='o',
color='black',
ecolor='lightgray',
elinewidth=3,
capsize=0);
重要参数
xerr, yerr : float or array-like, shape(N,) or shape(2, N), optional
- scalar: 所有数据点的对称 /-值。
- 形状(N,): 每个数据点的 /-值对称。
- 形状(2,N): 每个条数据单独的-和 值。第一行包含较低的误差,第二行包含较高的误差。
- None: 没有误差线。
fmt 是一种控制线条和点的外观的代码格式。语法与 plt.plot
的缩写代码相同。
加网格线
代码语言:javascript复制plt.grid(b=None, which='major', axis='both', **kwargs)
常用参数方式
plt.grid(axis=方向, color=颜色, linestyle=线型)
- axis : {'both', 'x', 'y'}, optional: 显示哪个方向的网格线
- which : {'major', 'minor', 'both'}, optional 根据主次坐标轴更改网格线
- color: 线的颜色
- linestyle: 有以下一些选择
- linewidth:设置网格线宽度。
线型 | 标记 |
---|---|
直线 | - |
虚线 | -- |
点线 | : |
点划线 | -. |
保存图片
plt.savefig(name, dpi, quality)
- name: 图片的名字, 如
name='picture.png'
- dpi: 要保存的图片的像素,值越大, 保存的图片越清晰
- quality: 仅当格式为
'jpg' or 'jpeg'
才能使用,从 1(最差)到 95(最好)
可以使用fig.canvas.get_supported_filetypes()
查看系统支持的文件格式。
移动坐标轴
使得轴刻度落在坐标轴上
代码语言:javascript复制# 创建画布对象
plt.figure(figsize=(8, 8), dpi=80)
# 获取当前的坐标对象
ax = plt.gca()
# 设置将X轴的刻度值放在底部X轴上
ax.xaxis.set_ticks_position('bottom')
# 设置将Y轴的刻度值放在左侧y轴上
ax.yaxis.set_ticks_position('left')
# 设置右边坐标轴线的颜色(设置为none表示不显示)
ax.spines['right'].set_color('none')
# 设置顶部坐标轴线的颜色(设置为none表示不显示)
ax.spines['top'].set_color('none')
# 设置底部坐标轴线的位置(设置在y轴为0的位置)
ax.spines['bottom'].set_position(('data', 0))
# 设置左侧坐标轴线的位置(设置在x轴为0的位置)
ax.spines['left'].set_position(('data', 0))
x = np.linspace(-1, 1, 100)
plt.plot(x, x**2);
多子图
可以在一张图上绘制多个图形,当然,也可以将不同的图形绘制到多个不同的区域当中。
子图有如下三种方式:
- 通过figure对象调用add_subplot方法。
- 通过plt的subplot方法。
- 通过plt的subplots方法。
plt.subplot()
plt.subplot
方法,由于plt可以隐式的创建一个figure对象
,因此使用这个方法,来指定绘图布局,不需要显示的创建figure对象
。因为plt.subplot
方法直接可以返回子绘图区域的axes对象
。
plt.subplots_adjust
方法可以用来调整子图与子图之间的距离。(left,right,top,bottom,wspace,hspace)
代码语言:javascript复制fig = plt.figure(figsize=(8, 5))
fig.subplots_adjust(hspace=0.4, wspace=0.4)
for i in range(1, 7):
ax = fig.add_subplot(2, 3, i)
ax.text(0.5, 0.5, str((2, 3, i)),fontsize=18, ha='center')
plt.subplots
通过plt的subplots方法
创建子绘图区域,该方法返回一个元组。如果是一个子绘图对象,那么返回的是一个axes坐标系对象
。如果是多个子绘图对象,则返回一个ndarray数组
。
代码语言:javascript复制fig, ax = plt.subplots(2, 3, sharex='col', sharey='row', figsize=(8, 5))
# 坐标轴存放在一个NumPy数组中,按照[row, col]取值
for i in range(2):
for j in range(3):
ax[i, j].text(0.5, 0.5, str((i, j)),fontsize=18, ha='center')
fg.add_subplot()
add_subplot
指定绘图布局,需要指定子绘图区域的行数、列数和当前要绘制的子区域。
add_subplot
方法会返回每个子绘图区域的对象,调用该对象即可实现在子区域的图形绘制。
可使用参数facecolor设置绘图区域的背景色。
代码语言:javascript复制x = np.linspace(-1, 1, 100)
fg = plt.figure(figsize=(8, 6), dpi=120)
#第一个子图
fg.add_subplot(2, 2, 1) # 两行两列的第一个
plt.plot(x, x)
plt.title('第一个子图')
plt.legend(["$y=x$"])
#第二个子图
fg.add_subplot(2, 2, 2) # 两行两列的第二个
plt.plot(x, x**2)
plt.title("第二个子图")
plt.legend(["$y=x^{2}$"], loc=4)
#第三个子图
fg.add_subplot(2, 2, 3)
# 获取当前的坐标对象
ax = plt.gca() # 这里获取的是这个子图的坐标对象, 也就是把这个子图的坐标轴改变
# 设置将X轴的刻度值放在底部X轴上
ax.xaxis.set_ticks_position('bottom')
# 设置将Y轴的刻度值放在左侧y轴上
ax.yaxis.set_ticks_position('left')
# 设置右边坐标轴线的颜色(设置为none表示不显示)
ax.spines['right'].set_color('none')
# 设置顶部坐标轴线的颜色(设置为none表示不显示)
ax.spines['top'].set_color('none')
# 设置底部坐标轴线的位置(设置在y轴为0的位置)
ax.spines['bottom'].set_position(('data', 0))
# 设置左侧坐标轴线的位置(设置在x轴为0的位置)
ax.spines['left'].set_position(('data', 0))
plt.plot(x, x**2)
plt.title("第三个子图")
plt.legend(["$y=x^{2}$"], loc=4, fontsize=5)
# 第四个子图
fg.add_subplot(2, 2, 4)
# 获取当前的坐标对象
ax = plt.gca() # 这里获取的是这个子图的坐标对象, 也就是把这个子图的坐标轴改变
# 设置将X轴的刻度值放在底部X轴上
ax.xaxis.set_ticks_position('bottom')
# 设置将Y轴的刻度值放在左侧y轴上
ax.yaxis.set_ticks_position('left')
# 设置右边坐标轴线的颜色(设置为none表示不显示)
ax.spines['right'].set_color('none')
# 设置顶部坐标轴线的颜色(设置为none表示不显示)
ax.spines['top'].set_color('none')
# 设置底部坐标轴线的位置(设置在y轴为0的位置)
ax.spines['bottom'].set_position(('data', 0))
# 设置左侧坐标轴线的位置(设置在x轴为0的位置)
ax.axis('equal') # 保证图形是圆的
ax.spines['left'].set_position(('data', 0))
plt.plot(x, (1-x**2)**0.5, color='r')
plt.plot(x, -(1-x**2)**0.5, color='r')
plt.title("第四个子图") # 标题
plt.legend(["$x^{2} y^{2}=1$"], loc=4, fontsize=5);
常用图形
折线图
常用参数形式:
plt.plot(x, y, marker=点的形状, color=颜色, linestyle=线形, linewidth=线宽, markersize=点的形状大小, alpha=透明度)
示例
代码语言:javascript复制x = np.linspace(-5, 5, 50)
# 创建画布
plt.figure(figsize=(8, 5))
plt.plot(x, x, color='r', marker='o', markersize=1, alpha=0.3)
plt.plot(x, np.sin(x), color='g', marker='p', markersize=5, alpha=0.6)
plt.plot(x, np.cos(x), color = 'y', marker='v', markersize=7, alpha=0.9)
plt.legend(["$y=x$", "$y=sin(x)$", "$y=cos(x)$"]);
散点图
常用参数形式:
plt.scatter(x, y, marker=点的形状, color=颜色, markersize=点的形状大小, alpha=透明度)
x = np.random.randn(500)
plt.figure(figsize=(8, 5))
plt.scatter(x, 1/(1 np.exp(-x)), alpha=0.4, color='r')
plt.scatter(x, np.tanh(x), marker='v', alpha=0.7, color='g')
plt.scatter(0, 0, color='r')
plt.text(0.2, 0, "(0, 0)")
plt.legend(["sigmoid", 'tanh'], loc=4, fontsize=15);
直方图
常用参数形式:
plt.bar(x, y, width=柱子宽度, color=颜色)
x = np.arange(10, 0, -2)
plt.figure(figsize=(8, 5))
plt.bar(range(len(x)), x, width=0.5, color='g')
plt.xticks(range(len(x)), ['一月', '二月', '三月', '四月', '五月'])
for i in list(zip(range(len(x)), x)):
plt.text(i[0], i[1] 0.1, i[1], horizontalalignment='center')#horizontalalignment='center'让数字在中间
plt.show();
饼图
常用参数形式:
plt.pie(x, labels=标签, autopct=指定显示数值, explode=突出显示某个部分)
#调节图形大小,宽,高
plt.figure(figsize=(7,8))
#定义饼状图的标签,标签是列表
labels = ['数据库', 'PowerBI', 'Python', 'Hive', '其他']
#每个标签占多大,会自动去算百分比
x = [35, 25, 25, 10, 5]
#将某部分爆炸出来, 使用括号,将第一块分割出来,数值的大小是分割出来的与其他两块的间隙
explode=[0.05, 0.00, 0, 0, 0]
patches,l_text,p_text = plt.pie(x,
explode=explode,
labels=labels,
# colors=colors,
labeldistance = 1.1,
autopct = '%3.1f%%',
shadow = False,
startangle = 90,
pctdistance = 0.6)
# labeldistance,文本的位置离远点有多远,1.1指1.1倍半径的位置
# autopct,圆里面的文本格式,%3.1f%%表示小数有三位,整数有一位的浮点数
# shadow,饼是否有阴影
# startangle,起始角度,0,表示从0开始逆时针转,为第一块。一般选择从90度开始比较好看
# pctdistance,百分比的text离圆心的距离
# patches, l_texts, p_texts,为了得到饼图的返回值,p_texts饼图内部文本的,l_texts饼图外label的文本
#改变文本的大小
#方法是把每一个text遍历。调用set_size方法设置它的属性
for t in l_text:
t.set_size(15)
for t in p_text:
t.set_size(18)
# 设置x,y轴刻度一致,这样饼图才能是圆的
plt.title("数据分析各技能占比", fontsize=20)
plt.axis('equal')
plt.show()
箱线图
代码语言:javascript复制np.random.seed(666)
x = np.random.randn(100)
plt.figure(figsize=(10, 6), dpi=80)
plt.boxplot(x,
sym='*', # 设定异常值形状
notch=True, # 是否在中位数处以凹凸口的形式显示箱线图
whis=1.5)
plt.plot(np.linspace(0,2, 100), np.full(100, 1.739251),
linestyle='--', color='y', label='上限')
plt.plot(np.linspace(0,2, 100), np.full(100, -1.942967),
linestyle='--', color='r', label='下限')
plt.plot(np.linspace(0,2, 100), np.full(100, -0.049283),
linestyle='--', color='g', label='中位数')
plt.legend()
plt.show();
画一个填充好颜色的形状
代码语言:javascript复制import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mptaches
%matplotlib inline
xy1=np.array([2,2])
xy2=np.array([1,7])
xy3=np.array([8,2])
xy4=np.array([8,8])
fig,ax=plt.subplots(figsize=(8, 5))
#圆形,指定坐标和半径
circle=mptaches.Circle(xy1, radius=2)
ax.add_patch(circle)
#长方形
rect=mptaches.Rectangle(xy2,width=3, height=1,color='r')
ax.add_patch(rect)
#多边形
polygon=mptaches.RegularPolygon(xy3,numVertices=6,radius=1.5,color='g')
ax.add_patch(polygon)
# 椭圆
ellipse=mptaches.Ellipse(xy4,width=4, height=2,color='c')
ax.add_patch(ellipse)
ax.axis('equal')
plt.show()
参考资料
[1]
(gallery): https://matplotlib.org/examples/pylab_examples/annotation_demo2.html
推荐阅读