查看全课大纲(第 44 / 51 节)
  1. 1.Python 是什么?为什么值得学?
  2. 2.如何为 Python 编程准备一个“全家桶”环境?
  3. 3.Python 有哪几种执行方法?
  4. 4.行与缩进到底有什么用?
  5. 5.注释有什么用,怎么写?
  6. 6.变量:如何给数据起个好名字?
  7. 7.运算符的优先级和常见坑点是什么?
  8. 8.Python 中,数字和布尔值究竟有哪几种?
  9. 9.输入函数 `input()` 和文件读取 `open()` 怎么用?
  10. 10.如何将程序的结果展示给用户或保存下来?
  11. 11.CSV 文件怎么读怎么写才方便?
  12. 12.列表是什么,如何创建和访问它?
  13. 13.列表的修改操作,有哪些方法?
  14. 14.列表切片为什么能取到部分元素?排序和查找又该怎么用?
  15. 15.判断语句:如何让程序根据条件做不同的事?
  16. 16.for 循环如何遍历序列中的元素?
  17. 17.while 循环什么时候才会停?
  18. 18.while 循环的结束条件,你写对了吗?
  19. 19.循环中途想提前结束,怎么办?
  20. 20.`break` 和 `continue` 到底有什么区别?
  21. 21.列表推导式如何让代码更简洁高效?
  22. 22.字符串怎么定义、拼接和操作?
  23. 23.元组:为什么定义单个元素时要加逗号?
  24. 24.集合(set)怎么用?如何快速去重和做集合运算?
  25. 25.字典是什么,为什么比列表更方便?
  26. 26.字典的增删改查与遍历,如何避免 KeyError?
  27. 27.函数里的变量,为什么有的能用有的不能用?
  28. 28.在函数内部修改全局变量,为什么有时不生效?
  29. 29.函数里能修改全局变量吗?返回值怎么用?
  30. 30.匿名函数:如何用 lambda 快速定义简单函数?
  31. 31.面向对象编程是什么,为什么需要它?
  32. 32.类中的方法和属性到底怎么定义和使用?
  33. 33.如何控制对对象内部属性和方法的访问?
  34. 34.异常发生时,程序会怎样继续执行?
  35. 35.如何组织代码:包和模块
  36. 36.`if __name__ == '__main__'` 到底有什么用?
  37. 37.如何用 IDE 的 Debug 功能排查程序错误?
  38. 38.Matplotlib 绘图的第一步该做什么?
  39. 39.Figure 是什么,如何设置图形尺寸?
  40. 40.如何自定义 Matplotlib 的坐标轴?
  41. 41.如何为图表添加图例,让不同曲线一目了然?
  42. 42.饼图怎么画才能直观展示数据占比?
  43. 43.如何用 Matplotlib 绘制散点图?
  44. 44.柱状图怎么画?
  45. 45.如何使用 Matplotlib 绘制等高线图?
  46. 46.如何在 Matplotlib 中绘制子图?
  47. 47.zip 函数如何把多个列表“打包”在一起?
  48. 48.如何给可迭代对象加上索引?
  49. 49.random 模块如何生成随机数?
  50. 50.math 模块怎么用?
  51. 51.Counter 如何快速统计元素出现次数?

柱状图怎么画?

约 7 分钟

小象实战讲义 · Python 编程从入门到实践

在数据可视化中,柱状图是用于比较不同类别数据大小的常用图表。本节将学习如何使用 Matplotlib 库的 bar 函数绘制柱状图,包括设置柱体颜色、边框以及为柱体添加数值标签。这是《数据可视化》章节中继折线图、散点图之后,又一个基础的图表绘制技能。

💡 核心导读

  • 核心函数:使用 plt.bar(x, height) 绘制柱状图,其中 x 是柱体的位置,height 是柱体的高度。
  • 样式定制:通过 facecolor 和 edgecolor 参数分别设置柱体的填充色和边框颜色。
  • 添加标签:使用 plt.text(x, y, s) 在指定坐标 (x, y) 处添加文本标签 s。
  • 坐标轴调整:使用 plt.xlim() 和 plt.ylim() 可以调整图表的显示范围。
  • 数据源兼容:bar 函数可以接受 Python 列表(list)或 NumPy 数组(ndarray)作为输入数据。

1. 绘制基础柱状图

柱状图通过不同高度的垂直(或水平)柱体来展示数据,柱体越高,代表数值越大,便于直观比较。

使用 matplotlib.pyplot.bar(x, height) 函数绘制。x 是一个序列,表示每个柱体在横轴(分类轴)上的位置;height 是另一个长度与 x 相同的序列,表示每个柱体的高度(数值)。

下面的示例将绘制两组对称的柱状图,一组在上半部分,一组在下半部分。

import matplotlib
matplotlib.use('Agg')  # 无图形界面后端
import matplotlib.pyplot as plt
import numpy as np

# 准备数据
n = 10  # 柱体数量
X = np.arange(n)  # 柱体的位置:0, 1, 2, ..., 9
# 计算柱体高度,这里使用一个简单的递减公式
Y1 = (1 - X / float(n))  # 上半部分数据
Y2 = (1 - X / float(n))  # 下半部分数据(与Y1相同)

plt.figure()  # 创建一张画板

# 绘制上半部分柱状图(Y1为正数)
plt.bar(X, +Y1)
# 绘制下半部分柱状图(将Y2取负,柱体向下生长)
plt.bar(X, -Y2)

# 设置坐标轴显示范围,为图形留出一些边距
plt.xlim(-.5, n)  # 横轴从-0.5到10
plt.ylim(-1.25, 1.25)  # 纵轴从-1.25到1.25

# 绘图完成后关闭图形以释放资源
plt.close()
print("基础柱状图绘制完成,包含上下两组对称柱体。")
基础柱状图绘制完成,包含上下两组对称柱体。

代码解读:

  • np.arange(n) 生成了一个从 0 到 n-1 的整数数组,作为柱体的位置。
  • Y1 和 Y2 是根据公式 1 - X/n 计算出的高度值,结果是一个值从 1 递减到 0.1 的数组。
  • 第一个 bar 调用绘制了高度为 +Y1 的柱体(正数,向上)。
  • 第二个 bar 调用绘制了高度为 -Y2 的柱体(负数,向下),实现了在下半部分绘图的效果。
  • plt.xlim 和 plt.ylim 用于调整坐标轴的显示范围,让图形看起来更协调。

2. 自定义柱体颜色与边框

默认的柱体颜色是单一的。我们可以通过 facecolor 参数设置柱体的填充色,通过 edgecolor 参数设置柱体边框的颜色。

颜色可以用以下几种方式指定:

  1. 十六进制 RGB 字符串:如 '#ff0000' 表示红色,'#0000ff' 表示蓝色。
  2. 颜色名称字符串:如 'red', 'blue', 'green', 'black', 'white'。
import matplotlib
matplotlib.use('Agg')  # 无图形界面后端
import matplotlib.pyplot as plt
import numpy as np

n = 10
X = np.arange(n)
Y1 = (1 - X / float(n))
Y2 = (1 - X / float(n))

plt.figure()

# 绘制上半部分柱体:红色填充,黑色边框
plt.bar(X, +Y1, facecolor='#ff0000', edgecolor='black')
# 绘制下半部分柱体:蓝色填充,白色边框
plt.bar(X, -Y2, facecolor='blue', edgecolor='white')

plt.xlim(-.5, n)
plt.ylim(-1.25, 1.25)

plt.close()
print("自定义颜色的柱状图绘制完成。上半部分红底黑边,下半部分蓝底白边。")
自定义颜色的柱状图绘制完成。上半部分红底黑边,下半部分蓝底白边。

3. 为柱体添加数值标签

为了更清晰地展示每个柱体的具体数值,可以在柱体的顶端(或内部)添加文本标签。这需要使用 plt.text(x, y, s) 函数。

  • x, y: 文本标签放置位置的坐标。
  • s: 要显示的文本字符串。
  • ha: 水平对齐方式('center', 'left', 'right')。
  • va: 垂直对齐方式('bottom', 'top', 'center', 'baseline')。

通常,我们将标签放在柱体的顶部中央。对于向下生长的柱体,则放在底部中央。

import matplotlib
matplotlib.use('Agg')  # 无图形界面后端
import matplotlib.pyplot as plt
import numpy as np

n = 10
X = np.arange(n)
Y1 = (1 - X / float(n))
Y2 = (1 - X / float(n))

plt.figure()

# 绘制柱体
plt.bar(X, +Y1, facecolor='#ff0000', edgecolor='black')
plt.bar(X, -Y2, facecolor='blue', edgecolor='white')

plt.xlim(-.5, n)
plt.ylim(-1.25, 1.25)

# 为上半部分柱体添加标签
for x, y in zip(X, Y1):
    # 在 (x, y) 位置添加文本,格式化为两位小数
    # ha='center': 水平居中
    # va='bottom': 垂直对齐到文本的底部(对于正数柱体,放在顶部)
    plt.text(x, y, '%.2f' % y, ha='center', va='bottom')

# 为下半部分柱体添加标签
for x, y in zip(X, Y2):
    # 对于负数柱体,标签放在柱体底部,所以y坐标是 -y
    # va='top': 垂直对齐到文本的顶部(对于负数柱体,放在底部)
    plt.text(x, -y, '%.2f' % y, ha='center', va='top')

plt.close()
print("带数值标签的柱状图绘制完成。标签显示了每个柱体的精确高度。")
带数值标签的柱状图绘制完成。标签显示了每个柱体的精确高度。

注意:text 函数中的 x, y 坐标是数据坐标,即它们与图表上数据点的坐标系一致。ha 和 va 控制的是文本自身相对于这个坐标点的对齐方式。

📝 动手练一练

假设你记录了本周一到周五的步数,数据如下:[8000, 12000, 9500, 11000, 7000]。请绘制一个柱状图来展示这些数据,要求:

  1. 柱体颜色为绿色 (facecolor='green')。
  2. 为每个柱体在顶部中央添加步数标签(例如 “8000”)。
  3. 将图表标题设置为 “Weekly Steps”。
👉 点击查看参考答案

思路:

  1. 用 ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'] 作为横坐标(x)。
  2. 用步数列表作为柱体高度(height)。
  3. 调用 bar 函数绘图,并设置 facecolor。
  4. 循环遍历每个柱体的位置和高度,使用 text 添加标签。
  5. 使用 plt.title 设置标题。
import matplotlib
matplotlib.use('Agg')  # 无图形界面后端
import matplotlib.pyplot as plt

# 数据
days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri']
steps = [8000, 12000, 9500, 11000, 7000]

plt.figure()

# 绘制柱状图
plt.bar(days, steps, facecolor='green', edgecolor='black')

# 添加数值标签
for day, step in zip(days, steps):
    plt.text(day, step, str(step), ha='center', va='bottom')

# 设置标题
plt.title('Weekly Steps')

plt.close()
print("周步数柱状图绘制完成。")
周步数柱状图绘制完成。

常见错误

错误写法现象或报错原因正确写法
plt.bar(x_positions, heights) 其中 x_positions 和 heights 长度不同图表显示异常或报错 ValueErrorbar 函数要求 x 和 height 两个序列的长度必须严格一致,因为它需要为每个 x 位置匹配一个 height 值。确保传入的两个列表或数组长度相同。例如:x = [0,1,2]; h = [10,20,30]。
使用 color 参数期望同时设置填充和边框只有填充色被改变,柱体上看不到边框线bar 函数中,color 参数是 facecolor 的别名,只控制填充色;不设置 edgecolor 时边框是透明的。要设置边框需使用 edgecolor。分别使用 facecolor 和 edgecolor 参数。例如:facecolor='red', edgecolor='black'。
plt.text(x, y, 'label') 标签位置不对或看不到标签出现在奇怪的位置或图表外text 的坐标 (x, y) 是数据坐标。如果 y 值远大于 ylim 设置的范围,标签就会显示在图表区域外。确保标签的 y 坐标在纵轴显示范围内。通常取柱体高度值 y 或稍高一点(如 y*1.05)。
直接使用 Python 列表而非 NumPy 数组进行计算TypeError: unsupported operand type(s) for /: 'list' and 'float'示例中 Y1 = (1 - X / float(n)) 如果 X 是普通列表,X / float(n) 在 Python 中是非法的。NumPy 数组支持这种向量化运算。对于数值计算,建议先转为 NumPy 数组,或使用列表推导式:Y1 = [1 - x/float(n) for x in X]。

小结

  1. 使用 matplotlib.pyplot.bar(x, height) 函数绘制柱状图,x 决定柱体位置,height 决定柱体高度。
  2. 通过 facecolor 和 edgecolor 参数可以自定义柱体的填充色和边框颜色,支持十六进制颜色码和颜色名称。
  3. 使用 plt.text(x, y, s, ha, va) 可以在图表指定坐标添加文本标签,常用于标注柱体的具体数值。
  4. ha(水平对齐)和 va(垂直对齐)参数控制文本相对于给定坐标点 (x, y) 的对齐方式。
  5. 柱状图的数据源可以是 Python 列表(list)或 NumPy 数组(ndarray),但进行向量运算时使用 NumPy 数组更方便。
  6. 通过 plt.xlim() 和 plt.ylim() 可以调整坐标轴的显示范围,使图表布局更合理。

📋 行动清单

  • 运行一遍本节的所有示例代码,观察上下对称柱状图的效果。
  • 修改“动手练一练”中的步数数据,并尝试将柱体颜色改为 'orange',边框改为 'darkred'。
  • 尝试将 plt.text 中的 va 参数从 'bottom' 改为 'top',观察标签位置的变化。

—— 小象教研组

配套资料 · 直接下载

课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。

  • 第5章代码包:柱状图(含1 个 Notebook)
    ZIP · 732B
    下载