前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python 数据可视化工具包 matplotlib

python 数据可视化工具包 matplotlib

作者头像
我是一条小青蛇
发布2019-10-23 14:32:04
8060
发布2019-10-23 14:32:04
举报
文章被收录于专栏:青笔原创青笔原创

matplotlib 是一个 python 的 2D 绘图库。大量的学术期刊,书籍出版物使用它来绘制专业的数据可视化图表。matplotlib 支持跨平台,可运行在 python 脚本,python 解释器, IPython,Jupyter notebook, web 应用服务器,以及四个 GUI(Graphical User Interface) 工具包中。使用matplotlib ,只需要几行代码,便可绘制折线图,直方图,功率谱(power spectra), 条形图,误差图,散点图等。

1. 安装

代码语言:javascript
复制
pip install matplotlib

2. 导入

ps: 在 jupyter notebook 环境需要添加 %matplotlib inline ,使得绘图生成在 notebook 页面。其他环境需要去掉 %matplotlib inline

代码语言:javascript
复制
import matplotlib.pyplot as plt
%matplotlib inline

3. 基本概念

matplotlib 中定义了四个基本概念:figure, axes, axis, artist。准确理解这四个基本概念,能更好的理解和熟练使用 matplotlib 绘制你想要的图表。

为了更直观的理解这四个概念,没有比直接使用 matplotlib 将这些抽象的概念绘制出来更好的方式了。

代码语言:javascript
复制
import numpy as np

figure, axes = plt.subplots(1, 2, figsize=(8, 4))
figure.suptitle("figure")

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

axes1, axes2 = axes

axes1.plot(x, x, label='artist legend')
axes2.plot(x, x**2, label='artist legend')

axes1.set_title("axes 1")
axes2.set_title("axes 2")

axes1.set_xlabel("axis x of axes 1")
axes2.set_xlabel("axis x of axes 2")

axes1.set_ylabel("axis y of axes 1")
axes2.set_ylabel("axis y of axes 2")

axes1.legend()
axes2.legend()

axes1.grid()
axes2.grid()

plt.show()

通过观察绘制出来的图表,我们可以很直观的看到,各个“抽象概念”的在图表中对应的具体表示,以及它们之间的层次关系。

有了这些可视化呈现,再来逐一理解它们,就很容易了。

3.1 figure

从图中可以看出,figure 表示整个绘图区域,它更多扮演的就是一个容器的角色,所有其他绘图元素都必须要包含在 figure 中,通过 figsize 参数限定 figure 大小,同时也限定了绘图区域的大小。此外,通过使用 figure.suptitle(title) 方法,也可以为整个绘图区域,设置一个标题,但这不是必需的(事实上,如果不给 figure 设置标题,我们这里就无法直观感知到它作为容器的存在)。

由此可见,要使用 matplotlib 绘制图表或任何可视化呈现,就必须先显式隐式(直接使用 plt.plot 等函数绘制时)创建一个 figure 对象。

下面,简单介绍两种最常用的创建 figure 的方法。根据个人习惯,可任选一种方式即可。个人更多使用第二种方式。

3.1.1 plt.figure(num=None, figsize=None, dpi=None, facecolor=None, edgecolor=None, frameon=True, clear=False)

plt.figure() 是任何创建 figure 对象的底层工厂函数。它提供创建 figure 了所有细节。

参数

描述

num

整数或字符串。figure 编号,即 figure 对象的 number 属性,可以理解为 figure 对象的 ID;如果编号为 num 的 figure 在上下文中已经存在,则直接返回存在 figure 引用,而不创建新的 figure; 默认为 None , 会创建一个新的 figure 对象,并将 number 加1 。

figsize

元组。figure 的宽高,单位 英尺。默认值为 matplotlib.rcParams["figure.figsize"] 。

dpi

整数。分辨率。默认值为 matplotlib.rcParams["figure.dpi"] 。

facecolor

字符串或颜色对象。背景颜色。默认为白色。

edgecolor

字符串或颜色对象。边框颜色。默认为白色。

frameon

Bool。

clear

Bool。为 True 时,清空当前已经存在的 figure 的绘制。默认不清空。

代码示例,理解 num 的作用:

代码语言:javascript
复制
figure1 = plt.figure()
print("this is a new figure instance, whose number is {}.\n".format(figure1.number))
figure2 = plt.figure()
print("this is a new figure instance, whose number is {}.\n".format(figure2.number))

figure1_ref = plt.figure(num=1) # 等效于 plt.figure(1)
print("this is a existed figure instance, whose number is {}.\n".format(figure1_ref.number))
if figure1_ref == figure1:
    print("figure1_ref is equal to figure1.")

plt.show()

可以看到,上面脚本运行后,并没有显示可见的图表。正如上文所说,figure 仅仅是个容器,真正我们所想到的包含在 figure 容器中,带有坐标系的一个个图表,是下文将要介绍的 axes 。使用 plt.figure() 方法创建的 figure 要显示图表,必须调用 plt.plot() 等绘制函数。代码如下:

代码语言:javascript
复制
# figure 1
plt.figure(figsize=(9, 3))
plt.suptitle("figure 1")

names = ['a', 'b', 'c']
values = [1, 10, 100]

plt.subplot(131)
plt.bar(names, values)

plt.subplot(132)
plt.scatter(names, values)

plt.subplot(133)
plt.plot(names, values)

plt.show()

# figure 2
plt.figure(figsize=(9, 3))
plt.suptitle("figure 2")

names = ['d', 'e', 'f']
values = [100, 10, 1]

plt.subplot(131)
plt.bar(names, values)

plt.subplot(132)
plt.scatter(names, values)

plt.subplot(133)
plt.plot(names, values)

plt.show()
3.1.2 plt.subplots(nrows=1, ncols=1, sharex=False, sharey=False, figsize=None)

plt.subplots() 是 plt.figure() 的上层封装,提供了一次创建 figure 和 axes 便捷方式。事实上,除了 nrows,ncols,sharex,sharey 等新增的参数,任何 plt.figure() 支持的参数,都可以通过 plt.subplots() 传递, 例如 figsize 参数。

plt.subplots() 它返回一个元组。元组的第一个元素为 figure 对象;第二个元素是用于绘制图表的 axes 对象,需要注意的是,通过参数 nrows,ncols 创建不只一个 axes 时,元组的第二个元素是一个 axes 对象的 numpy 数组。

可见,不同于 plt.figure() ,plt.subplots() 在创建 figure 对象时,同时也创建了一个或多个 axes 对象。因此,创建后就可以看到图表。

如下代码,创建了包含 2 行 3 列,共 6 个 axes 的 figure 对象。

代码语言:javascript
复制
figure, axes = plt.subplots(2, 3, figsize=(9, 6))
figure.suptitle("2 rows 3 cols")
plt.show()

print("type of return tuple[1] is {}".format(type(axes)))

如果省略 nrowsncols, 将只创建一个 axes。如下:

代码语言:javascript
复制
figure, axes = plt.subplots()
figure.suptitle("only one axes")
plt.show()

print("type of return tuple[1] is {}".format(type(axes)))

3.2 axes

“This is what you think of as ‘a plot’”.

经过上面的论述,相信理解上面这句话,简直 “So easy!”。没错,axes 正是我们绘制各种绚丽图表的真正主角!

上文已经提到,使用 plt.subplots() 方法创建图表,会返回所包含的 axes 对象。这些 axes 对象就是 matplotlib 提供绘制图表的面向对象接口。使用 axes 对象的各种绘制方法,可以在图表中对应 axes 坐标空间,绘制任何图表,文字和图片。

3.2.1 plot([x], y, [fmt])

以 x 为横轴,y 为纵轴,fmt 为格式字符串(定义颜色,标记,线型等),绘制线图或标记。并且可以定义多个 x, y, fmt 组合,一次绘制多个不同图形。

以下提供一些绘制示例。

在同一个 axes 中绘制不同图形

代码语言:javascript
复制
figure, axes = plt.subplots()
t = np.arange(0., 5., 0.2)

axes.plot(t, t, 'r--', t, t**2, 'bs', t, t**3, 'g^')

plt.show()

在一个 figure 中的两个 axes 绘制不同图形,并且共享 x 轴(axis):

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

figure, axes = plt.subplots(2, 1, sharex=True)
ax1, ax2 = axes

ax1.plot(t1, f(t1), 'bo', t2, f(t2), 'k')
ax2.plot(t2, np.cos(2*np.pi*t2), 'r--')

plt.show()
3.2.2 散点图: scatter(x, y, s=None, c=None, alpha=None)

x 横轴;y 纵轴;s 点的大小,默认是 rcParams['lines.markersize'] 的平方;c 颜色;alpha 透明度。

代码语言:javascript
复制
np.random.seed(19680801)

N = 50
x = np.random.rand(N)
y = np.random.rand(N)
colors = np.random.rand(N)
area = (30 * np.random.rand(N))**2 

plt.scatter(x, y, s=area, c=colors, alpha=0.5)

plt.show()
3.2.3 条形图: bar(x, height, width=0.8)

x 横坐标位置; height 条形高度; width 条形宽度。

代码语言:javascript
复制
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

labels = ['G1', 'G2', 'G3', 'G4', 'G5']
men_means = [20, 34, 30, 35, 27]
women_means = [25, 32, 34, 20, 25]

x = np.arange(len(labels))  # 标签位置
width = 0.35  # 条形宽度

fig, ax = plt.subplots()
# 绘制条形图
rects1 = ax.bar(x - width/2, men_means, width, label='男')
rects2 = ax.bar(x + width/2, women_means, width, label='女')

ax.set_ylabel('得分')
ax.set_title('分小组性别得分')
ax.set_xticks(x)
ax.set_xticklabels(labels)
ax.legend()


def autolabel(rects):
    """在每个条形上添加文本,显示条形的高度"""
    for rect in rects:
        height = rect.get_height()
        ax.annotate('{}'.format(height),
                    xy=(rect.get_x() + rect.get_width() / 2, height),
                    xytext=(0, 3),  # 增加三个点的垂直偏移
                    textcoords="offset points",
                    ha='center', va='bottom')


autolabel(rects1)
autolabel(rects2)

fig.tight_layout()

plt.show()
3.2.4 水平条形图: barh(y, width, height=0.8)

y 纵坐标位置; width 条形宽度; height 条形高度。

代码语言:javascript
复制
category_names = ['Strongly disagree', 'Disagree',
                  'Neither agree nor disagree', 'Agree', 'Strongly agree']
results = {
    'Question 1': [10, 15, 17, 32, 26],
    'Question 2': [26, 22, 29, 10, 13],
    'Question 3': [35, 37, 7, 2, 19],
    'Question 4': [32, 11, 9, 15, 33],
    'Question 5': [21, 29, 5, 5, 40],
    'Question 6': [8, 19, 5, 30, 38]
}


def survey(results, category_names):
    """
    Parameters
    ----------
    results : dict
        A mapping from question labels to a list of answers per category.
        It is assumed all lists contain the same number of entries and that
        it matches the length of *category_names*.
    category_names : list of str
        The category labels.
    """
    labels = list(results.keys())
    data = np.array(list(results.values()))
    data_cum = data.cumsum(axis=1)
    category_colors = plt.get_cmap('RdYlGn')(
        np.linspace(0.15, 0.85, data.shape[1]))

    fig, ax = plt.subplots(figsize=(9.2, 5))
    ax.invert_yaxis()
    ax.xaxis.set_visible(False)
    ax.set_xlim(0, np.sum(data, axis=1).max())

    for i, (colname, color) in enumerate(zip(category_names, category_colors)):
        widths = data[:, i]
        starts = data_cum[:, i] - widths
        ax.barh(labels, widths, left=starts, height=0.5,
                label=colname, color=color)
        xcenters = starts + widths / 2

        r, g, b, _ = color
        text_color = 'white' if r * g * b < 0.5 else 'darkgrey'
        for y, (x, c) in enumerate(zip(xcenters, widths)):
            ax.text(x, y, str(int(c)), ha='center', va='center',
                    color=text_color)
    ax.legend(ncol=len(category_names), bbox_to_anchor=(0, 1),
              loc='lower left', fontsize='small')

    return fig, ax


survey(results, category_names)
plt.show()
3.2.5 饼图: pie(data, explode=None, labels=None, colors=None, autopct=None..)
代码语言:javascript
复制
fig, ax = plt.subplots(figsize=(8, 4), subplot_kw=dict(aspect="equal"))

recipe = ["375 g flour",
          "75 g sugar",
          "250 g butter",
          "300 g berries"]

data = [float(x.split()[0]) for x in recipe]
ingredients = [x.split()[-1] for x in recipe]


def func(pct, allvals):
    absolute = int(pct/100.*np.sum(allvals))
    return "{:.1f}%\n({:d} g)".format(pct, absolute)


wedges, texts, autotexts = ax.pie(data, autopct=lambda pct: func(pct, data),
                                  textprops=dict(color="w"))

ax.legend(wedges, ingredients,
          title="Ingredients",
          loc="center left",
          bbox_to_anchor=(1, 0, 0.5, 1))

plt.setp(autotexts, size=8, weight="bold")

ax.set_title("Matplotlib bakery: A pie")

plt.show()
3.2.6 直方图 hist(data, bins=None, range=None, density=None, weights=None…)
代码语言:javascript
复制
np.random.seed(19680801)

# 样本数据
mu = 100  # 均值
sigma = 15  # 标准差
x = mu + sigma * np.random.randn(437)

num_bins = 50

fig, ax = plt.subplots()

# 绘制直方图
n, bins, patches = ax.hist(x, num_bins, density=1)

# 最佳拟合线
y = ((1 / (np.sqrt(2 * np.pi) * sigma)) *
     np.exp(-0.5 * (1 / sigma * (bins - mu))**2))

ax.plot(bins, y, "--")
ax.set_xlabel("智商")
ax.set_ylabel("概率密度")
ax.set_title("IQ直方图: 平均值=100, 标准差=15")

# 调整间距以防止 ylabel 被遮挡
fig.tight_layout()
plt.show()
3.2.7 2维直方图: hist2d(x, y, bins=10, range=None, density=False, weights=None, …)
代码语言:javascript
复制
import matplotlib.colors as mcolors
from numpy.random import multivariate_normal

data = np.vstack([
    multivariate_normal([10, 10], [[3, 2], [2, 3]], size=100000),
    multivariate_normal([30, 20], [[2, 3], [1, 3]], size=1000)
])

gammas = [0.8, 0.5, 0.3]

fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(8, 6))

axes[0, 0].set_title('Linear normalization')
axes[0, 0].hist2d(data[:, 0], data[:, 1], bins=100)

for ax, gamma in zip(axes.flat[1:], gammas):
    ax.set_title(r'Power law $(\gamma=%1.1f)$' % gamma)
    ax.hist2d(data[:, 0], data[:, 1],
              bins=100, norm=mcolors.PowerNorm(gamma))

fig.tight_layout()

plt.show()
3.2.8 显示图片: imshow(X)
代码语言:javascript
复制
with open('dog.jpeg', 'rb') as image_file:
    image = plt.imread(image_file)

fig, ax = plt.subplots()
ax.imshow(image)
ax.set_title("Hi, 我们又见面了!")

ax.axis('off')
plt.show()

3.3 axis

虽然 axis 和 axes 中文翻译都是轴的意思,但是,axes 的意思更像是由 axis 构成的坐标空间,正如上文介绍的,我们可以在这个坐标空间绘制各种图像和显示图片;如果说 axes 是抽象意义的“轴”,那么 axis 就是真正意义的坐标轴;2维绘图中,只有两个 axis 即 横轴 x 和纵轴 y。由于 axis 是构成 axes 一部分,因此我们可以使用 axes 对象的方法,来设置 x 轴和 y 轴的属性。

代码语言:javascript
复制
figure, axes = plt.subplots(1, 2, figsize=(6, 3))

ax1, ax2 = axes

# 设置坐标显示区间
xmin, xmax, ymin, ymax = 0, 10, 50, 100
ax1.axis([xmin, xmax, ymin, ymax])

# 隐藏 axis
ax2.set_axis_off()
ax2.set_title("axis off.")

plt.show()

3.4 artist

artist 中文翻译是艺术家,在 matplotlib 中,它具有更一般的意义,即所有可见的元素都是 artist。如: title, legend, grid, axis, tick, label, text等等。

代码语言:javascript
复制
np.random.seed(19680801)
data = np.random.randn(2, 100)

fig, axs = plt.subplots(2, 2, figsize=(5, 5))
axs[0, 0].hist(data[0])
axs[1, 0].scatter(data[0], data[1])
axs[0, 1].plot(data[0], data[1])
axs[1, 1].hist2d(data[0], data[1])

plt.show()

参考

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-09-082,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 安装
  • 2. 导入
  • 3. 基本概念
    • 3.1 figure
      • 3.1.1 plt.figure(num=None, figsize=None, dpi=None, facecolor=None, edgecolor=None, frameon=True, clear=False)
      • 3.1.2 plt.subplots(nrows=1, ncols=1, sharex=False, sharey=False, figsize=None)
    • 3.2 axes
      • 3.2.1 plot([x], y, [fmt])
      • 3.2.2 散点图: scatter(x, y, s=None, c=None, alpha=None)
      • 3.2.3 条形图: bar(x, height, width=0.8)
      • 3.2.4 水平条形图: barh(y, width, height=0.8)
      • 3.2.5 饼图: pie(data, explode=None, labels=None, colors=None, autopct=None..)
      • 3.2.6 直方图 hist(data, bins=None, range=None, density=None, weights=None…)
      • 3.2.7 2维直方图: hist2d(x, y, bins=10, range=None, density=False, weights=None, …)
      • 3.2.8 显示图片: imshow(X)
    • 3.3 axis
      • 3.4 artist
      • 参考
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档