数据处理04:Python数学绘图库Matplotlib

Matplotlib 是一个用于实现数据可视化的绘图工具包,可以根据各种数据生成不同类型的精美图形,并具有良好的跨平台兼容性。项目官网 https://matplotlib.org/

04_matplotlib.png

Matplotlib 已包含于 Anaconda 中,导入时请按惯例命名为 mpl:

In [1]: import matplotlib as mpl

In [2]: mpl.__version__
Out[2]: '3.0.3'

Matplotlib 自带的西文字库并不支持大字符集,以下代码通过指定中文字库文件路径创建了一个备用的字体属性对象,这是解决中文显示问题的一种简便办法:

In [3]: from matplotlib.font_manager import FontProperties
   ...: # cfont = FontProperties(fname="/usr/share/fonts/truetype/wqy/wqy-microhei.ttc")
   ...: cfont = FontProperties(fname=r"C:\Windows\Fonts\simhei.ttf")

Matplotlib 绘图时通常使用其中的 pyplot 模块,约定的别名为 plt,其 API 接口的风格与商业数学软件 MATLAB 保持一致。以下代码引入了 pyplot 模块,还使用 IPython 的魔法命令来设定 Matplotlib 使用 inline 显示方式即输出为“内联”的图像——你也可以选择 notebook 方式,它专用于 Jupyter 笔记本页面,带有图像缩放和平移等附加交互功能。

In [4]: import matplotlib.pyplot as plt
   ...: %matplotlib inline
   ...: # %matplotlib notebook

Matplotlib 包含大量的绘图工具,本文只能做简要的入门介绍,更多细节请参阅官方文档 https://matplotlib.org/contents.html

在开始绘图之前,让我们首先生成 30 个标准正态分布的伪随机数作为练习数据:

In [5]: import numpy as np
   ...: i = np.random.standard_normal(30)
   ...: i
Out[5]: 
array([ 0.05853444, -0.35528836, -0.49311672, -0.62192003,  0.55390535,
       -1.89540927, -1.54782971, -1.42975649,  1.14476468,  0.40167794,
        1.62419468,  0.40548133,  0.14817515, -0.51935529,  0.05247306,
        1.38867876,  0.49215373,  0.50926899, -2.14022901, -0.93915824,
       -0.70473312, -0.33102008, -0.21256037, -1.71685258, -0.88803382,
       -1.25251899, -1.2733392 ,  0.46163637,  0.27706922, -0.2548643 ])

最基本的二维绘图函数是 plt.plot(),原则上它需要两组数值作为参数,分别表示横坐标值和纵坐标值。但也可以只传入一个序列,这时是根据序列的索引和值来绘图,默认类型为简单的线图:

plt.plot(i);
plt.title("简单线图", fontproperties=cfont, fontsize=18);
04_mpl_pic1.png

可以看到图形的横坐标就是数组索引,纵坐标则是数组的值。运行程序文件时应在最后调用 plt.show() 函数显示图形,在交互模式下则不需要。这段代码还调用了 plt.title() 函数来设置标题文本,注意要显示汉字就必须以 fontproperties 参数指定之前创建的字体属性对象。

在数据参数之后还可以传入一个字符串参数来设定图形样式,包括颜色、标记和线型,三者都是可选项,如省略则会显示默认样式。以下代码新加了一条正弦图形,所用的样式“ro:”表示红色、圆形标记、点虚线:

plt.plot(i)
plt.title("线图叠加", fontproperties=cfont, fontsize=18)
j = np.linspace(0, 30, 100)  # 0到30之间均匀间隔的100个数值(默认50个)
plt.plot(j, np.sin(j), "ro:");
04_mpl_pic2.png

样式字符串可用颜色符有红绿蓝青品黄黑白(rgbcmykw),可用线型符有“-”“--”“-.”和“:”,以下代码新加了演示可用标记符的语句,plt.plot() 函数还有许多关键字参数,例如设置标记大小的 markersize 和设置标签的 label,调用 plt.legend() 即可显示图例:

plt.plot(i, label="随机数据")
plt.title("线图叠加和标记", fontproperties=cfont, fontsize=18)
j = np.linspace(0, 30, 100)
plt.plot(j, np.sin(j), "ro:", label="正弦曲线")
k = 0
for marker in ".,ov^<>1234sp*hH+xDd|_":
    plt.plot(k, k%3+2, marker, markersize=10)
    k += 1
plt.legend(prop=cfont);
04_mpl_pic3.png

使用其他函数可以绘制不同种类的图形,例如适用于多维数据可视化的 plt.scatter() 函数,以下代码是使用随机的位置大小颜色数据生成散点图的例子:

x = np.random.randn(100)
y = np.random.randn(100)
colors = np.random.rand(100)
sizes = 1000 * np.random.rand(100)
plt.scatter(x, y, c=colors, s=sizes, alpha=0.3, cmap="cool")  # 位置/颜色/大小/透明度/颜色映射集
plt.colorbar();
04_mpl_pic4.png

对于包含多个子图的复杂场景,推荐使用 Matplotlib 的面向对象接口:下面的例子调用 plt.subplots() 函数创建两个子图,然后调用每个子图对应轴域(Axes)对象的方法分别绘制不同的图形:

# 面向对象接口,使用 Figure 和 Axes 的方法
fig, ax = plt.subplots(2)
ax[0].plot(j, np.sin(j))
ax[1].bar(j, np.cos(j)+1, color="pink");
04_mpl_pic5.png

接下来的例子是用 Matplotlib 绘图来展示 Python 官方文档中文翻译项目的进度,注意读取数据后需要将索引设为时间类型,这段程序选择了更漂亮的 ggplot 图形风格,并用到了更多的图形元素例如为关键数据点添加注释信息等:

import pandas as pd
# 短网址对应的原文件
# https://gitee.com/freesand/pyStudy/raw/master/data/py_cn.csv
py_cn = pd.read_csv("http://t.cn/EaRaPhp")
# py_cn = pd.read_csv("py_cn.csv")
py_cn.index = pd.to_datetime(py_cn.date)
plt.style.use("ggplot")  # 设置图形风格,可用的风格见plt.style.available,默认值为"default"
plt.figure(figsize=(10, 6))  # 设置图像大小,单位为英寸
ax = plt.axes()  # 创建轴域
ax.set_title("Python文档翻译进度图", fontproperties=cfont, fontsize=18)
ax.set(ylim=(0, 1), xlim=(pd.to_datetime("2018/11/01"), pd.to_datetime("2019/04/30")))
d = "2018/11/13", "2019/03/30", "2019/04/20"
ax.annotate("10%", xy=(d[0], .1), xytext=(d[0], .2), ha="center", arrowprops=dict(arrowstyle="simple"))
ax.annotate("20%", xy=(d[1], .2), xytext=(d[1], .3), ha="center", arrowprops=dict(arrowstyle="simple"))
ax.annotate("30%", xy=(d[2], .3), xytext=(d[2], .4), ha="center", arrowprops=dict(arrowstyle="simple"))
ax.plot(py_cn.index, py_cn.percent, "go--", linewidth=2, label="进度百分比")
ax.fill_between(py_cn.index, py_cn.percent)
ax.legend(prop=cfont, loc="upper left");
04_mpl_py_cn.png

中文版文档翻译进度达到 20% 时已被官方加入到语言选择框,可以看到在随后这段时间里速度明显提升,有更多志愿者参与其中,当然距离最终完成还有很长的路要走……希望大家继续关注这个项目 https://github.com/python/python-docs-zh-cn

——编程原来是这样……

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,042评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,996评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,674评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,340评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,404评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,749评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,902评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,662评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,110评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,451评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,577评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,258评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,848评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,726评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,952评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,271评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,452评论 2 348

推荐阅读更多精彩内容