Fork me on GitHub

数据分析与数据挖掘 - 08图形绘制

一 图的基本构成

1 画图的基本介绍

Matplotlib是数据可视化工作中,最常用的一个可视化库。Matplotlib有非常多的图形,我们很难在短时间内将其掌握,所以我们首先要掌握的是画图的思路和常用的一些图形。创建一个图的步骤大致可以分为9步,当然这9步并不是每一次都需要,只要你知道一个完整的图形可以有这么多的步骤就可以。每一个步骤对应着一个操作和操作它的函数。

  1. 导入模块:import matplotlib.pyplot as plt
  2. 定义图像窗口:plt.figure()
  3. 画图:plt.plot(x, y)
  4. 定义坐标轴范围:x轴:plt.xlim()/y轴:plt.ylim() lim其实就是limit的缩写
  5. 定义坐标轴名称:x轴:plt.xlabel()/plt.ylabel()
  6. 定义坐标轴刻度及名称:plt.xticks()/plt.yticks()
  7. 设置图像边框颜色:ax = plt.gca() ax.spines[].set_color()
  8. 调整刻度位置:ax.xaxis.set_ticks_position()/ax.yaxis.set_ticks_position()
  9. 调整边框(坐标轴)位置:ax.spines[].set_position()

2 画图的基本代码

下面请跟随我的代码一起来画一个图感受一下吧!

import numpy as np
import matplotlib.pyplot as plt

# np.linspace将会在-5到5的区间内生成100个数,注意这个是均匀分布的
x = np.linspace(-5, 5, 100)

# 根据x的值,经过计算生成y1和y2的值
y1 = 2 * x + 1
y2 = x ** 2

# 画图
plt.plot(x, y1)
plt.plot(x, y2, color='red', linewidth=1.0, linestyle='--')

# 显示
plt.show()

这样我们就画出来一个简单的图形了,接下来我们继续在刚刚画的这个图形中添加一些元素。

3 中文显示的问题处理

我们要做的事情就是重新定义坐标轴的名称,在定义坐标轴的名称的时候,我们会遇到一个问题,就是中文显示 的问题,这个问题是绕不过去的问题。

对于Windows系统的同学只需在代码中添加如下代码:

# 解决中文显示问题
font = {"family" : "SimHei",
 "size" : "20"}
plt.rc("font", **font)

对于mac系统的同学来说,稍微有点麻烦,在terminal里面输入:fc-list :lang=zh,如果显示command not found,那么我们需要执行一个安装命令:conda install fontconfig,然后输入y确认就可以自动安装好了,最后再一次输入fc-list :lang=zh,就可以查看字体了,然后我们在代码中添加下面一行代码:

plt.rcParams["font.family"] = 'Arial Unicode MS'

4 完整的画图代码

下面让我们一起来把这个绘图完善起来,代码如下:

import numpy as np
import matplotlib.pyplot as plt

# np.linspace将会在-5到5的区间内生成100个数,注意这个是均匀分布的
x = np.linspace(-5, 5, 100)

# 根据x的值,经过计算生成y1和y2的值
y1 = 2 * x + 1
y2 = x ** 2

# font = {"family" : "SimHei",
#  "size" : "20"}
# plt.rc("font", **font)
plt.rcParams["font.family"] = 'Arial Unicode MS'

# 设置画布大小
plt.figure(figsize=(8, 5))

# 画图
plt.plot(x, y1)
plt.plot(x, y2, color='red', linewidth=1.0, linestyle='--')

# 设置坐标轴范围
plt.xlim((-3, 5))
plt.ylim((-4, 5))

# 设置坐标轴名称
plt.xlabel('我是x轴')
plt.ylabel('我是y轴')

# 显示
plt.show()

5 刻度的修改

我们看到,在坐标轴上还会有一些刻度的存在,我们只需要在上边的代码后边加入一段代码,就可以进行刻度的修改了:

new_ticks = np.linspace(-1, 2, 5)
# 设置坐标轴的刻度
plt.xticks(new_ticks)
plt.yticks([-2, -1.8, -1, 1.22, 3], ["北京", "天津", "河北", "东北", "山东"])

6 边框的修改

除此之外,我们还可以做一些图形边框上的修改,在本章最开始我们已经说过关于图形边框修改的方法了,我们只需要把下面的代码添加至末尾即可:

# 添加边框
ax = plt.gca()
# 修改右侧颜色
ax.spines["right"].set_color("green")
# 修改左侧颜色
ax.spines["left"].set_color("orange")
# 修改顶部颜色
ax.spines["top"].set_color("yellow")
# 修改底部颜色
ax.spines["bottom"].set_color("purple")

一起来看一下现实的效果怎么样
image.png
这里需要注意的是,如果上下左右只操作其中的左侧和底部,那么其他两条线将仍然默认是黑色,还有另外一个小技巧,我们上面的图形总是在一个方框中显示,我们可以把右侧和顶部的线条不设置颜色,这样看起来就与我们平时的坐标轴看起来一个样子了,也就是把设置边框的代码修改为:

ax.spines["right"].set_color("none")
ax.spines["top"].set_color("none")
plt.show()

修改之后看起来就好多了
image.png

7 修改边框的位置

在数学中,我们的图形有时是十字的样式,那下面我们一起来看一下,如何修改边框的位置,代码其实也很简单,我们首先来修改一下x轴对应y轴的位置,完整的代码如下:

import numpy as np
import matplotlib.pyplot as plt

# np.linspace将会在-5到5的区间内生成100个数,注意这个是均匀分布的
x = np.linspace(-5, 5, 100)

# 根据x的值,经过计算生成y1和y2的值
y1 = 2 * x + 1
y2 = x ** 2

# font = {"family" : "SimHei",
#  "size" : "20"}
# plt.rc("font", **font)
plt.rcParams["font.family"] = 'Arial Unicode MS'

# 设置画布大小
plt.figure(figsize=(8, 5))

# 画图
plt.plot(x, y1)
plt.plot(x, y2, color='red', linewidth=1.0, linestyle='--')

# 设置坐标轴范围
plt.xlim((-3, 5))
plt.ylim((-4, 5))

# 设置坐标轴名称
plt.xlabel('我是x轴')
plt.ylabel('我是y轴')

# 设置坐标轴的刻度
plt.xticks(np.linspace(-1, 2, 5))
plt.yticks([-2, -1.8, -1, 1.22, 3], ["北京", "天津", "河北", "东北", "山东"])

# 添加边框
ax = plt.gca()
# 修改右侧颜色
ax.spines["right"].set_color("none")
# 修改左侧颜色
ax.spines["left"].set_color("orange")
# 修改顶部颜色
ax.spines["top"].set_color("none")
# 修改底部颜色
ax.spines["bottom"].set_color("purple")

# 设置x轴的位置
ax.xaxis.set_ticks_position("bottom")
ax.spines["bottom"].set_position(("data", 0))
# 设置y轴的位置
ax.yaxis.set_ticks_position("left")
ax.spines["left"].set_position(("data", 0))

# 显示
plt.show()

这样就大功告成了,最后再来看一下现实的图形
image.png

8 添加图例说明

最后在画图时我们可以使用label参数给图片添加一个图例说明,最后使用legend显示出来,最终代码如下:

import numpy as np
import matplotlib.pyplot as plt

# np.linspace将会在-5到5的区间内生成100个数,注意这个是均匀分布的
x = np.linspace(-5, 5, 100)

# 根据x的值,经过计算生成y1和y2的值
y1 = 2 * x + 1
y2 = x ** 2

# font = {"family" : "SimHei",
#  "size" : "20"}
# plt.rc("font", **font)
plt.rcParams["font.family"] = 'Arial Unicode MS'

# 设置画布大小
plt.figure(figsize=(8, 5))

# 画图
plt.plot(x, y1, label='y1图例说明')
plt.plot(x, y2, color='red', linewidth=1.0, linestyle='--', label='y2图例说明')

# 设置坐标轴范围
plt.xlim((-3, 5))
plt.ylim((-4, 5))

# 设置坐标轴名称
plt.xlabel('我是x轴')
plt.ylabel('我是y轴')

# 设置坐标轴的刻度
plt.xticks(np.linspace(-1, 2, 5))
plt.yticks([-2, -1.8, -1, 1.22, 3], ["北京", "天津", "河北", "东北", "山东"])

# 添加边框
ax = plt.gca()
# 修改右侧颜色
ax.spines["right"].set_color("none")
# 修改左侧颜色
ax.spines["left"].set_color("orange")
# 修改顶部颜色
ax.spines["top"].set_color("none")
# 修改底部颜色
ax.spines["bottom"].set_color("purple")

# 设置x轴的位置
ax.xaxis.set_ticks_position("bottom")
ax.spines["bottom"].set_position(("data", 0))
# 设置y轴的位置
ax.yaxis.set_ticks_position("left")
ax.spines["left"].set_position(("data", 0))

# fontdict 是对字体大小和颜色进行设置,如果这里会对原图有遮挡,我们可以重新设置画布大小
plt.text(1, -1, "这是我对图片添加的一段说明", fontdict={"size": 12, "color": "r"})

# 显示
plt.legend(loc='lower right')  # 图例说明没有参数则默认在右上角
plt.show()

二 绘制统计图形

1 柱状图

在实际的企业应用中,我们要掌握多种图形的绘制,并且深度结合自己的应用场景,用合适的图形来展示适合它的数据场景,使得数据更具有说明力。

首先我们来学习一下bar()函数,它的功能是在x轴上绘制定性数据的分布特征,也就是柱状图。使用方法是plt.bar(x,y),其中x表示在x轴上的定性数据的类别,而y表示每种定性数据的类别的数量。如果你觉得有点抽象,那我们就直接上代码吧。

import matplotlib.pyplot as plt

# x是刻度,y是高度
x = [1, 2, 3, 4, 5, 6, 7, 8]
y = [3, 1, 4, 5, 7, 8, 6, 4]

plt.bar(x, y)

plt.show()

代码非常简单,分别定义好了x和y并且带入函数里面就可以了,它的现实结果其实就是一个条形图。
image.png

2 频率分布直方图

与条形图相对比的是频率直方图(frequency histogram),也叫做频率分布直方图,是统计学中表示频率分布的图形。在直角坐标系中,用横轴表示随机变量的取值,横轴上的每个小区间对应一个组的组距,作为小矩形的底边;纵轴表示频率(频数/组距=频率),并用它作小矩形的高,以这种小矩形构成的一组图称为频率直方图。

import matplotlib.pyplot as plt
import numpy as np

x = np.random.randint(0, 10, 20)
print(x)

plt.hist(x)
plt.show()

随机x输出结果:[9 7 4 1 0 9 8 3 7 8 1 1 7 4 6 8 0 6 9 9]
image.png

3 饼图

下面要学习的就是饼图,饼图是一种用来表示数据所占比例最常用的图形,它的函数是pie(),使用方法也非常的简单,我们进行最简单的图形调用的时候也可以只传一个参数,就像这样plt.pie(x)。

import matplotlib.pyplot as plt

# 中文显示
plt.rcParams["font.family"] = 'Arial Unicode MS'

# 声明类别
kinds = ['苹果', '香蕉', '西红柿', '西瓜']

# 这个是16进制颜色码,你可以在网上搜索16进制颜色码就可以获取到所有的编码
colors = ['#e41a1c', '#DDA0DD', '#4B0082', '#7FFFAA']

sold_nums = [4, 3, 2, 5]

# 绘制饼图,根据图形效果,看一下这些参数的含义吧
plt.pie(sold_nums,
        labels=kinds,
        colors=colors)

plt.show()

饼图显示结果
image.png

4 极线图

接下来我们看一下极线图的绘制方法,我们可以使用plt.polar(theta,x)这样的方式来进行图形的绘制,如果你之前没接触过这种图形,解释起来有一点复杂,我们直接来看一下效果吧。

import matplotlib.pyplot as plt
import numpy as np

bar_slices = 10  # 星星数量
theta = np.linspace(0.0, 2*np.pi, bar_slices, endpoint=False)
r = 30*np.random.rand(bar_slices)
print(r)

# linewidth为线条粗细,mfc为星星颜色,ms为星星大小
plt.polar(theta, r, color='chartreuse', linewidth=2, marker='*', mfc='y', ms=10)
plt.show()

r输出结果为:[19.19557439  9.80163298 14.72266501 25.96471826 17.43950265 27.16974937
24.16166493  8.32586511  1.07374567 21.5498875 ]
image.png

5 散点图

接下来要学习的图形叫做散点图,也有叫做气泡图的。我们可以使用plt.scatter(x,y)这样的方式来进行图形的绘制。关于scatter的参数:

  • x就表示x轴上的值
  • y就表示y轴上的值
  • s表示散点标记的大小,这个是可选项
  • c表示散点标记的颜色,可选项
  • cmap表示将浮点数映射成颜色的颜色映射表

让我们通过一段代码的演示,来看看实践一下这些参数。自己可以根据我的说明尝试着修改一下这些参数。

import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl

a = np.random.randn(100)
b = np.random.randn(100)

"""
cmap的参数非常多,cm后面的gist_rainbow可以有很多替代
具体的可以在官网或者源代码中查询使用,不过都把差别不大,就是颜色上的区别
"""
plt.scatter(a, b, s=np.power(10*a+20*b, 2),
            c=np.random.rand(100),
            cmap=mpl.cm.gist_rainbow,
            marker='o')  # marker表示散点的样式,可以试试用o,*或者^

plt.show()

展示结果如图所示:
image.png

6 棉棒图

下面我们来讲解一下棉棒图的绘制方法,棉棒图主要用来绘制离散有序的数据,使用方法是plt.stem(x,y)。关于它的参数有:

  • x:用来指定棉棒的x轴基线上的位置。
  • y:棉棒的长度。
  • linefmt:棉棒的样式。
  • markerfmt:棉棒末端的样式。
  • basefmt:指定基线的样式。

我们直接上代码来看一下

import matplotlib.pyplot as plt
import numpy as np

# linspace:在0.5和2*np.pi之间返回20个均匀间隔的数据
x = np.linspace(0.5, 2 * np.pi, 20)
# randn:返回20个服从标准正态分布的样本数据
y = np.random.randn(20)

# --是虚线,-是实线
plt.stem(x, y, linefmt='--', markerfmt='o', basefmt='-')
plt.show()

显示结果如下图所示:
image.png

7 箱线图

接下来我们来绘制一下箱线图,箱线图的绘制方法也比较简单,我们使用plt.boxplot(x)来实现,x就是我们要输入的数据了。

import matplotlib.pyplot as plt
import numpy as np

x = np.random.randn(1000)
plt.boxplot(x)
plt.show()

显示结果如下图所示:
image.png

三 图形参数说明

1 柱状图参数详解

我们再次来看一下柱状图,柱状图在数据的可视化展示用应用的场景非常的多了,比如按照月份的商品销量展示,销售人员的业绩统计等等场景我们都会用到。现在我在原有代码基础之上加入一些新的参数,代码如下:

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5]
y = [6, 10, 4, 5, 1]

# 中文显示
plt.rcParams["font.family"] = 'Arial Unicode MS'

plt.bar(
    # 1 柱体的标签值
    x,
    # 2 柱体的高度
    y,
    # 3 柱体的对齐方式,两个参数:edge或者center
    align='edge',
    # 4 颜色
    color='b',
    # 5 刻度的标签值,用字母把x中的数字替换
    tick_label=['A', 'B', 'C', 'D', 'E'],
    # 6 透明度
    alpha=0.5
)

plt.xlabel('产品代号')
plt.ylabel('产品销量')

# 网格设置
plt.grid(
    True,
    # 1 axis指的是对轴的设置,参数可以为x,y或者both
    axis='x',
    # 2 ls指的是网格的样式,也可以写成--或者:
    ls=':',
    color='r',
    alpha=0.9
)

plt.show()

显示结果如下图所示:
image.png

2 条形图参数详解

条形图其实就是把柱状图横过来放,它们的使用方法一样,只是调用的函数不同,参数全部相同,具体代码如下:

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5]
y = [6, 10, 4, 5, 1]

# 中文显示
plt.rcParams["font.family"] = 'Arial Unicode MS'

# 函数改为了barh,只是添加了一个h,代表horizontal水平横放
plt.barh(
    # 1 柱体的标签值
    x,
    # 2 柱体的高度
    y,
    # 3 柱体的对齐方式,两个参数:edge或者center
    align='edge',
    # 4 颜色
    color='b',
    # 5 刻度的标签值,用字母把x中的数字替换
    tick_label=['A', 'B', 'C', 'D', 'E'],
    # 6 透明度
    alpha=0.5
)

plt.xlabel('产品代号')
plt.ylabel('产品销量')

# 网格设置
plt.grid(
    True,
    # 1 axis指的是对轴的设置,参数可以为x,y或者both
    axis='x',
    # 2 ls指的是网格的样式,也可以写成--或者:
    ls=':',
    color='r',
    alpha=0.9
)

plt.show()

显示结果如下图所示:
image.png

3 堆积图参数详解

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5]
y = [6, 10, 4, 5, 1]
y1 = [2, 6, 3, 4, 5]

# 中文显示
plt.rcParams["font.family"] = 'Arial Unicode MS'

plt.figure(figsize=(8, 5))
plt.bar(
    x,
    y,
    align='center',
    color='#66c2a5',
    tick_label=['A', 'B', 'C', 'D', 'E'],
    label='男人'
)
plt.bar(
    x,
    y1,
    align='center',
    bottom=y,  # 指定哪一值在下面
    color='#8da0cb',
    label='女人'
)
plt.xlabel('城市代号')
plt.ylabel('男女比例')

plt.legend()
plt.show()

显示结果如下图所示:
image.png

4 堆积条形图参数详解

同理,堆积条形图就是把堆积图横放,原来需要考虑底部的是哪一个值,现在需要思考的是左边的是哪一个值,具体代码如下:

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5]
y = [6, 10, 4, 5, 1]
y1 = [2, 6, 3, 4, 5]

# 中文显示
plt.rcParams["font.family"] = 'Arial Unicode MS'

plt.figure(figsize=(8, 5))
plt.barh(x, y, align='center', color='#66c2a5', tick_label=['A', 'B', 'C', 'D', 'E'], label='男人')

# 这里修改了left 指定哪个值在这个图的下边
plt.barh(x, y1, align='center', left=y, color='#8da0cb', label='女人')

plt.xlabel('城市代号')
plt.ylabel('男女比例')

plt.legend()
plt.show()

显示结果如下图所示:
image.png

5 分块图参数详解

堆积图可以展示多数据形式上的差异,但有时不是特别明显,这是用分块图就可以很直观的比较出来。分块图可以分为多数据并列柱状图和多数据并列条形图,我们先来一起看一下多数据并列柱状图,具体代码如下:

import matplotlib.pyplot as plt
import numpy as np

# 中文显示
plt.rcParams["font.family"] = 'Arial Unicode MS'

x = np.arange(5)
y = [6, 10, 4, 5, 1]
y1 = [2, 6, 3, 8, 5]

bar_width = 0.35
tick_label = ['A', 'B', 'C', 'D', 'E']
plt.figure(figsize=(8, 5))

plt.bar(
    x,
    y,
    bar_width,
    color='c',
    align='center',
    label='男人',
    alpha=0.5
)

plt.bar(
    x+bar_width,
    y1,
    bar_width,
    color='b',
    align='center',
    label='女人',
    alpha=0.3
)

plt.xlabel('城市代号')
plt.ylabel('男女比例')

plt.xticks(x+bar_width/2, tick_label)

plt.legend()
plt.show()

图形显示结果如下图所示:
image.png

6 多数据并列条形图详解

根据我们的前面的讲解,你应该已经知道了,我们只需要把函数bar改为barh就可以,代码如下所示:

import matplotlib.pyplot as plt
import numpy as np

# 中文显示
plt.rcParams["font.family"] = 'Arial Unicode MS'

x = np.arange(5)
y = [6, 10, 4, 5, 1]
y1 = [2, 6, 3, 8, 5]

bar_width = 0.35
tick_label = ['A', 'B', 'C', 'D', 'E']
plt.figure(figsize=(8, 5))

plt.barh(
    x,
    y,
    bar_width,
    color='c',
    align='center',
    label='男人',
    alpha=0.5,
    hatch='\/'  # 如果我们需要添加一些装饰线可以使用hatch参数
)

plt.barh(
    x+bar_width,
    y1,
    bar_width,
    color='b',
    align='center',
    label='女人',
    alpha=0.3,
    hatch='\\'  
)

plt.xlabel('城市代号')
plt.ylabel('男女比例')

plt.xticks(x+bar_width/2, tick_label)

plt.legend()
plt.show()

图形显示结果如下图所示:
image.png

7 堆积折线图参数详解

堆积折线图是通过绘制不同数据集的折线图而生成的,按照垂直方向上彼此堆叠且又不互相覆盖的排列顺序,绘制若干条折线图而形成的组合图形。

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(1, 6, 1)
y = [0, 4, 3, 5, 6]
y1 = [1, 3, 4, 2, 7]
y2 = [3, 4, 1, 6, 5]

labels = ['2018', '2019', '2020']
colors = ['r', 'b', 'y']

plt.stackplot(x, y, y1, y2, labels=labels, colors=colors)

plt.legend()
plt.show()

图形显示结果如下图所示:
image.png

8 间断条形图参数详解

间断条形图是在条形图的基础之上绘制而成的,主要用来可视化定性数据的相同指标在时间维度上的指标值的变化情况,直观比较并展现出定性数据的相同指标的变化情况。

import matplotlib.pyplot as plt
import numpy as np

# 中文显示
plt.rcParams["font.family"] = 'Arial Unicode MS'

plt.broken_barh(
    # 元组中第一个元素代表距离y轴的距离,第二个元素代表自身的宽度
    [(10, 20), (190, 60), (270, 80), (370, 80)],
    # 元组中第一个元素代表距离x轴的距离,第二个元素代表自身的长度
    (30, 9),
    facecolors='r'
)

plt.broken_barh(
    [(30, 80), (190, 60), (270, 80), (360, 30)],
    (10, 5),
    facecolors=('b', 'y', 'g', 'purple')
)

# 定义坐标轴的范围
plt.xlim(0, 500)
plt.ylim(5, 50)

# 定义x轴的名称
plt.xlabel('上课时间')

# 定义x轴的刻度
plt.xticks(np.arange(0, 361, 60))

# 定义y轴的刻度和名称
plt.yticks([15, 25], ['一班', '二班'])

# 定义刻度的样式
plt.grid(ls='--', lw=1, color='gray')

# 定义主题名称
plt.title('两个班级的上课时间')

plt.show()

图形显示结果如下图所示:
image.png

9 阶梯图参数详解

阶梯图就如其名字那样,像一台阶一样,时而上升,时而下降,我们经常用它来展示数据的趋势变化或周期顾虑。阶梯图经常使用在时间序列的数据的可视化任务中,比如商品的日销量、月销量,企业中每月的员工数量的变化等,这样我们能够很容易发现时序数据的波动周期和规律。

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(1, 10, 10)
print(x)
y = np.sin(x)
print(y)

# 代码1
plt.step(x, y, color='b', where='pre', lw=2)
plt.xlim(0, 12)
plt.ylim(-1.2, 1.2)
plt.xticks(np.arange(1, 13, 1))
plt.grid(ls='--', lw=1, color='gray')
plt.show()

# 代码2 
plt.step(x, y, color='b', where='mid', lw=2)
plt.xlim(0, 12)
plt.ylim(-1.2, 1.2)
plt.xticks(np.arange(1, 13, 1))
plt.grid(ls='--', lw=1, color='gray')
plt.show()

# 代码3
plt.step(x, y, color='b', where='post', lw=2)
plt.xlim(0, 12)
plt.ylim(-1.2, 1.2)
plt.xticks(np.arange(1, 13, 1))
plt.grid(ls='--', lw=1, color='gray')
plt.show()

这里有一个新的参数where,你可以分别运行这三段代码,可以看到图形好像是在往右边移动,显示结果如下图所示:
代码1:
image.png
代码2:
image.png
代码3:
image.png
where参数主要用来定义step应该放在哪里,我们把图形中的每条横线可以看作一个step,where字段一共有三个取值,分别是:pre,mid和post,如果我们在x为1和2的两个位置上画一条横线(如上图红线所示),你会发现,当where='pre'时,y取值的第一个点应该是在x第一个点左侧一些,当where='mid'时,y取值的第一个点应该是在x第一个点中间,y取值的第一个点应该是在x第一个点右侧。

四 实例项目自由绘图

1 直方图

直方图擅长展示区间分布,比如某一科目的考试成绩,按照地区统计的人均寿命,发达国家与发展中国家人均可支配收入等等,现在我们需要绘制某个班级中Python语言考试成绩的分布区间图。

import matplotlib.pyplot as plt
import numpy as np

# 中文显示
plt.rcParams["font.family"] = 'Arial Unicode MS'

scores = np.random.randint(0, 100, 100)
bins = range(0, 101, 10)

"""
histtype在这里有三个参数,分别是bar,step和stepfilled
1 bar就是填满相应颜色
2 step是阶梯图
3 histtype是生成一个默认的lineplot进行图形填充填充,恰好这个参数的默认值就是bar
"""
plt.hist(x=scores, bins=bins, color='#3366FF', histtype='bar')
plt.xlabel('Python考试成绩')
plt.ylabel('学生成绩')

plt.show()

图形显示结果如下图所示:
image.png
在这里我们有必要重新再来说一下关于直方图与柱状图,因为他们的样子实在是太像了,只是柱体与柱体之间是否存在空隙,但恰恰是由于这一点,才让它们有所区别,也让它们分为擅长表示不同类型的数据。我们知道数据可以分为连续型数据和离散型数据,这里我们可以对它们进行总结。直方图擅长总结和描述连续型数据的分布,而柱状图更加的擅长描述和总结离散型数据的分布,所以你在未来的应用场景中,首先判断数据的特点,然后再决定使用什么图形去描述这些数据。

2 堆叠直方图

现在我们要绘制一个基于刚刚的场景之上的另外一个场景,就是我们要比较两个班级的Python语言考试的成绩,对它们的分布情况进行分别的比对,这时就需要用到堆叠直方图。

import matplotlib.pyplot as plt
import numpy as np

# 中文显示
plt.rcParams["font.family"] = 'Arial Unicode MS'

# 1 分别生成两个班级的分数
scores1 = np.random.randint(0, 100, 100)
scores2 = np.random.randint(0, 100, 100)

# 2 把两个班级的分数放在一个列表中
x = [scores1, scores2]

# 3 选择两个对比较鲜明的颜色
colors = ['r', 'b']

# 4 声明两个标签
labels = ['一班', '二班']

# 5 设定x轴的范围
bins = range(0, 101, 10)

"""
新加入的参数的意义:
1 rwidth:柱体的宽度,0.0-1.0
2 stack:上下排还是左右排
"""
plt.hist(x, color=colors, histtype='bar', rwidth=1.0, stacked=False, label=labels)
plt.xlabel('Python成绩分布')
plt.ylabel('人数')
plt.title('不同班级的Python成绩直方图')

plt.legend(loc=1)  # 原来用upper right这些,现在1表示右上,234分别对应逆时针旋转位置
plt.show()

图形显示结果如下图所示:
image.png

3 分裂式饼图

饼图是用来展示定性数据分布比例特征的统计图形,在数据可视化时应用的非常广泛,我们可以通过绘制饼图,直观的观察出数据的占比情况。饼图同样适用于离散型数据的占比情况,比如班级内男女性别比例,公司销售业绩每月在全年中的占比情况等等。对于比例分布的场景,饼图都是非常适合的。

import matplotlib.pyplot as plt
import numpy as np

plt.rcParams["font.family"] = 'Arial Unicode MS'

labels = ['第一季度', '第二季度', '第三季度', '第四季度']
sale = [20, 40, 30, 70]
colors = ['r', 'b', 'y', 'green']

explode = (0.1, 0.1, 0.1, 0.1)

plt.pie(
    sale,
    explode=explode,  # 裂开的那条缝的宽度
    labels=labels,
    autopct='%.2f%%',  # %的精度
    startangle=10,  # 从x轴为起始位置,逆时针旋转的角度
    shadow=True,  # 阴影
    colors=colors
)

plt.title('每一季度销售额', loc='right')
plt.show()

图形显示结果如下图所示:
image.png

4 内嵌环形饼图

内嵌环形饼图式使得饼图不仅可以展示单一数据集的比例情况,还可以对比展示多数据集的分布情况。

import matplotlib.pyplot as plt
import numpy as np

plt.rcParams["font.family"] = 'Arial Unicode MS'

development_language = ['Java', 'Python', 'C++', 'PHP', 'Scala']

weight1 = [40, 20, 30, 15, 15]
weight2 = [25, 35, 30, 12, 13]

colors = ['#FF6600', '#9966FF', '#663333', '#3399CC', '#666600']

wedges1, texts1, autotexts1 = plt.pie(
    weight1,
    autopct='%.1f%%',
    radius=1,
    pctdistance=0.85,
    colors=colors,
    textprops=dict(color='w'),
    wedgeprops=dict(width=0.3, edgecolor='w')
)

"""
饼图的创建其实是有三个返回值的:
1 一个序列,matplotlib.patches.Wedge的实例
2 一个列表,matplotlib.text.Text的实例,是label的列表
3 一个列表,matplotlib.text.Text的实例,是数值的文本实例标签,只有在参数autopct不为空的时候才有效
"""
print(wedges1)
print(texts1)
print(autotexts1)

wedges2, texts2, autotexts2 = plt.pie(
    weight2,
    autopct='%.1f%%',
    radius=0.75,
    pctdistance=0.75,
    colors=colors,
    textprops=dict(color='w'),
    wedgeprops=dict(width=0.5, edgecolor='b')  # 边框
)

plt.legend(
    weight1,
    development_language,
    fontsize=5,
    title='开发语言占比',
    loc='center left',
    bbox_to_anchor=(0.91, 0, 0.3, 1)
)

# 调整饼图外圈中的字体
plt.setp(autotexts1, size=10, weight='bold')

# 调整饼图内圈中的字体
plt.setp(autotexts2, size=15, weight='bold')

plt.title('开发语言使用人数比例表')
plt.show()

图形显示结果如下图所示:
image.png
综上代码,其实,饼图的嵌套,就是画两个饼图,不要让他们重叠。

5 箱型图

箱型图主要应用在一系列测量或者比较数据的观测中,比如学校与学校之间或者班级与班级之间的成绩比较,各个运动员之间的体能比较,产品优化前和产品优化后的各项数据指标展现的结果比较等等,箱型图是数据分析场景应用的比较多的一种数据可视化图形。

import matplotlib.pyplot as plt
import numpy as np

plt.rcParams["font.family"] = 'Arial Unicode MS'

# 生成正态分布数据
test1 = np.random.randn(5000)
test2 = np.random.randn(5000)

test_list = [test1, test2]

labels = ['随机数生成1', '随机数生成2']

colors = ['#3399FF', '#CCCCFF']

box_plot = plt.boxplot(
    test_list,
    whis=1.5,  # 上下四分位距离
    widths=0.6,
    sym='o',
    labels=labels,
    patch_artist=True,  # 是否给箱体添加颜色
    notch=True  # 是否中间v型凹陷
)

for patch, color in zip(box_plot['boxes'], colors):
    patch.set_facecolor(color)


plt.ylabel('随机数值')
plt.title('生成器抗干扰能力的稳定性比较')

plt.grid(axis='y', ls=':', lw=1, color='gray', alpha=0.2)

plt.show()

图形显示结果如下图所示:
image.png
以上是我们绘制的一些常用的图形和一些常用的参数,当然Matplotlib绘制图形的能力远不止于此,但如果每一个图形都一一讲一遍的话,那么内容会全部都由画图来组成了。画图的重点是要学习画图的思想,遇到问题先不要急于去画,首先一定要选定一个合适的图形,然后再动手。最核心的图形无非就是那几个常用的,我们都已经进行过了多次的练习。画图是数据分析、数据挖掘、AI方向的算法工程师必备的技能,所以一定要多多的练习它们的绘制。我们还会在后续的章节中不断的去使用这些图形的练习。

最后会有一个小练习,请点击下方链接下载题目和数据:
chapter8-1.zip

posted @ 2020-09-30 00:51  马一特  阅读(912)  评论(1编辑  收藏  举报