上节课我们讲了折线图的绘制,使用的是 plot 函数。当我们使用 plot 方法绘图时,默认绘制的是折线图。本节课我们来讲下条形图的绘制。

# 1.什么是条形图?

条形图(bar chart)是用宽度相同的条形的高度或长短来表示数据多少的图形,是一种用于对不同类别进行数值比较的统计图表。条形图可以横置或纵置,纵置时也称为柱形图(column chart)。条形图被误用的一个典型代表就是篡改 y 轴,对读者视觉造成误导。在使用条形图时,务必要原点位于 0。此外,注意对条形图进行排序。依据可视化的目的、以及想突出的重点信息,确定合理的排序标准,避免条形图看起来杂乱无章。

# 2.竖直条形图的绘制

竖直条形图的绘制使用 bar 函数。

from matplotlib import pyplot as plt

ages_x = [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]

dev_y = [38496, 42000, 46752, 49320, 53200, 56000, 62316, 64928, 67317, 68748, 73752]
plt.bar(ages_x, dev_y, label="全部开发者")

plt.xlabel("年龄")
plt.ylabel("年薪")
plt.title("年龄和薪水的关系")

plt.legend()

plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14

在上面的代码中,我们将 plot 函数改为 bar 函数,这样便绘制了条形图。执行完上述代码得到的图形如下图所示:

image.png 上面图形中只包含一类数据的条形图,和折线图一样,我们可以在一个图形中做多类数据的条形图,例如:

from matplotlib import pyplot as plt

ages_x = [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]

dev_y = [38496, 42000, 46752, 49320, 53200, 56000, 62316, 64928, 67317, 68748, 73752]
py_dev_y = [45372, 48876, 53850, 57287, 63016, 65998, 70003, 70000, 71496, 75370, 83640]

plt.bar(ages_x, dev_y, label="全部开发者")
plt.bar(ages_x, py_dev_y, label="Python开发者")

plt.xlabel("年龄")
plt.ylabel("年薪")
plt.title("年龄和薪水的关系")

plt.legend()

plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

在上面的代码中,我们又添加了一类数据的条形图,执行完上述代码,得到的图形如下图所示: image.png 从上述图形中,我们可以发现,虽然我们作了两类数据的条形图,但是只显示出一类数据的条形图,这是因为另一类数据的条形图被覆盖了。接下来,我们来解决这个问题。

import numpy as np
from matplotlib import pyplot as plt

ages_x = [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]
x_indexes = np.arange(len(ages_x))
width = 0.33

dev_y = [38496, 42000, 46752, 49320, 53200, 56000, 62316, 64928, 67317, 68748, 73752]
py_dev_y = [45372, 48876, 53850, 57287, 63016, 65998, 70003, 70000, 71496, 75370, 83640]

plt.bar(x_indexes, dev_y, width=width, label="全部开发者")
plt.bar(x_indexes + width, py_dev_y, width=width, label="Python开发者")

plt.xlabel("年龄")
plt.ylabel("年薪")
plt.title("年龄和薪水的关系")

plt.legend()

plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

在上面的代码中,我们创建了一个和列表 ages_x 长度相同的 ndarray(x_indexes),在作图时,用 ndarray(x_indexes) 替换横坐标。一类数据的横坐标为 x_indexes,另一类数据的横坐标为 x_indexes 中每个元素加上一个宽度(width),另外在调用 bar 函数时,传入 width 参数,表示条形图的宽度。执行完上述代码后的图形如下图所示: image.png 仔细观察上述图形,虽然我们将两类数据的条形图分开了,但是横坐标的数据同时也变成了 0~10,这显然是不正确的,因为原来的横坐标为表示年龄的数据,下面我们来解决这个问题。

import numpy as np
from matplotlib import pyplot as plt

ages_x = [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]
x_indexes = np.arange(len(ages_x))
width = 0.33

dev_y = [38496, 42000, 46752, 49320, 53200, 56000, 62316, 64928, 67317, 68748, 73752]
py_dev_y = [45372, 48876, 53850, 57287, 63016, 65998, 70003, 70000, 71496, 75370, 83640]

plt.bar(x_indexes, dev_y, width=width, label="全部开发者")
plt.bar(x_indexes + width, py_dev_y, width=width, label="Python开发者")

plt.xlabel("年龄")
plt.ylabel("年薪")
plt.title("年龄和薪水的关系")

plt.legend()

plt.xticks(ticks = x_indexes, labels = ages_x)

plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

上面代码中,我们使用 xticks 函数将 x_indexes 替换为 ages_x。执行完上述代码后的图形如下图所示: image.png 我们发现横坐标的数据变为了年龄。和折线图一样,我们可以使用自带的样式来生成图形,例如:

import numpy as np
from matplotlib import pyplot as plt

plt.style.use('fivethirtyeight')

ages_x = [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]
x_indexes = np.arange(len(ages_x))
width = 0.33

dev_y = [38496, 42000, 46752, 49320, 53200, 56000, 62316, 64928, 67317, 68748, 73752]
py_dev_y = [45372, 48876, 53850, 57287, 63016, 65998, 70003, 70000, 71496, 75370, 83640]

plt.bar(x_indexes, dev_y, width=width, label="全部开发者")
plt.bar(x_indexes + width, py_dev_y, width=width, label="Python开发者")

plt.xlabel("年龄")
plt.ylabel("年薪")
plt.title("年龄和薪水的关系")

plt.legend()

plt.xticks(ticks = x_indexes, labels = ages_x)

plt.tight_layout()

plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

执行完上述代码后,生成的图形如下图所示: image.png

# 3.水平条形图的绘制

我们首先来看使用纵置条形图来绘制有什么问题。例如:

import numpy as np
from matplotlib import pyplot as plt

languages = ['JavaScript', 'HTML/CSS', 'SQL', 'Python', 'Java', 'Bash/Shell/PowerShell', 
             'C#', 'PHP', 'C++','TypeScript']

popularity = [59219, 55466, 47544, 36443, 35917, 27097, 23030, 20524, 18523, 18017]

plt.bar(languages, popularity)

plt.title('最流行的编程语言')
plt.xlabel('编程语言')
plt.ylabel('流行度')

plt.tight_layout()

plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

执行完上述代码后的图形如下图所示: image.png 从上图中可以看出,横坐标上的数据标签已经重叠在一起了,下面我们使用横置条形图来改变这种情况,例如:

import numpy as np
from matplotlib import pyplot as plt

plt.style.use('fivethirtyeight')

languages = ['JavaScript', 'HTML/CSS', 'SQL', 'Python', 'Java', 'Bash/Shell/PowerShell', 
             'C#', 'PHP', 'C++','TypeScript']

popularity = [59219, 55466, 47544, 36443, 35917, 27097, 23030, 20524, 18523, 18017]

plt.barh(languages, popularity)

plt.title('最流行的编程语言')
plt.xlabel('流行度')
plt.ylabel('编程语言')

plt.tight_layout()

plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

想要绘制横置的条形图,只需要将 bar 函数改为 barh 函数即可。执行完上述代码后生成的图形如下图所示: image.png 改成横置的条形图后,解决了标签重叠的问题。上面的图形中,最流行的语言在图形的最下面,一般情况下,我们希望最流行的语言在最上面,我们只需要对数据进行翻转即可。例如:

import numpy as np
from matplotlib import pyplot as plt

plt.style.use('fivethirtyeight')

languages = ['JavaScript', 'HTML/CSS', 'SQL', 'Python', 'Java', 'Bash/Shell/PowerShell', 
             'C#', 'PHP', 'C++','TypeScript']

popularity = [59219, 55466, 47544, 36443, 35917, 27097, 23030, 20524, 18523, 18017]

languages.reverse()
popularity.reverse()

plt.barh(languages, popularity)

plt.title('最流行的编程语言')
plt.xlabel('流行度')
plt.ylabel('编程语言')

plt.tight_layout()

plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

上面的代码中,调用 reverse 函数对列表 languages 和 popularity 进行翻转,执行完上述代码后生成的图形如下图所示: image.png

# 4.应用场景

# 4.1 适用场景

条形图最适合对分类的数据进行比较。尤其是当数值比较接近时,由于人眼对于高度或长度的感知优于其他视觉元素(如面积、角度等),因此,使用条形图更加合适。

# 4.2 不适用场景

条形图要求至少一个分类变量,它们之间是离散的,绘制条形图时,条形和条形之间有间隔。如果是连续变量,则应当使用直方图,绘制出每个区间的数值,条形之间是连续的、没有间隔。

# 5.总结

本节课我们讲述了条形图的绘制,包括竖直条形图和水平条形图。还介绍了条形图的适用场景和不适用场景。

更新于: 12/30/2021, 2:39:56 AM