前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >数据可视化 | 手撕 Matplotlib 绘图原理(二)

数据可视化 | 手撕 Matplotlib 绘图原理(二)

作者头像
数据STUDIO
发布2021-06-24 11:06:01
1.4K1
发布2021-06-24 11:06:01
举报
文章被收录于专栏:数据STUDIO数据STUDIO

由于篇幅限制,将文章分为两部分,这是第二部分。

点击链接《 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=透明度)

代码语言:javascript
复制
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=颜色)

代码语言:javascript
复制
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=突出显示某个部分)

代码语言:javascript
复制
#调节图形大小,宽,高
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

推荐阅读

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-03-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据STUDIO 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 线条样式
  • 在图上添加文本
    • 示例:节假日对美国出生率的影响
    • 添加箭头和文字说明
    • 误差线
    • 加网格线
    • 保存图片
    • 移动坐标轴
      • 使得轴刻度落在坐标轴上
      • 多子图
        • plt.subplot()
          • plt.subplot方法,由于plt可以隐式的创建一个figure对象,因此使用这个方法,来指定绘图布局,不需要显示的创建figure对象。因为plt.subplot方法直接可以返回子绘图区域的axes对象。
            • plt.subplots_adjust方法可以用来调整子图与子图之间的距离。(left,right,top,bottom,wspace,hspace)
              • plt.subplots
                • 通过plt的subplots方法创建子绘图区域,该方法返回一个元组。如果是一个子绘图对象,那么返回的是一个axes坐标系对象。如果是多个子绘图对象,则返回一个ndarray数组。
                  • fg.add_subplot()
                  • 常用图形
                    • 折线图
                      • 散点图
                        • 直方图
                          • 饼图
                            • 箱线图
                              • 画一个填充好颜色的形状
                                • 参考资料
                                领券
                                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档