Python入门第13课:数据可视化入门,用Matplotlib绘制你的第一张图表
Python入门第13课:数据可视化入门,用Matplotlib绘制你的第一张图表
作者: 蛋皮
标签: Python, Matplotlib, 数据可视化, 绘图, 数据分析, Seaborn
欢迎回到Python入门系列!在前两节课中,我们掌握了如何使用requests
库获取数据,并用pandas
这个神器对数据进行清洗和分析。然而,分析的结果往往是一堆数字和表格,如何让这些信息更直观、更生动地呈现出来?如何让非技术人员也能一眼看懂数据背后的故事?
答案就是——数据可视化 (Data Visualization)。
今天,我们将学习Python中最基础、最强大的绘图库:Matplotlib。它是Python可视化领域的“老大哥”,几乎所有的高级可视化库(如Seaborn
, Plotly
)都建立在它的基础之上。掌握Matplotlib,就等于拿到了打开数据可视化世界大门的钥匙。
为什么选择 Matplotlib?
- 功能强大且全面: 支持绘制折线图、柱状图、散点图、直方图、饼图、3D图等几乎所有常见图表类型。
- 高度可定制: 几乎可以控制图表的每一个细节(颜色、线型、字体、标签、图例、坐标轴等)。
- 社区庞大,文档丰富: 作为最老牌的库,遇到问题很容易找到解决方案。
- 与Pandas无缝集成:
pandas
的DataFrame
和Series
可以直接调用.plot()
方法,底层就是Matplotlib。
一句话:Matplotlib是Python数据可视化的基石,是每个数据工作者的必备技能。
准备工作:安装与导入
Matplotlib通常随Anaconda一起安装。如果没有,使用pip安装:
pip install matplotlib
在Python脚本中导入:
import matplotlib.pyplot as plt
# 惯例:导入matplotlib.pyplot模块并简写为plt
重要提示: 如果你在Jupyter Notebook中运行,需要添加以下魔法命令,让图表直接显示在Notebook中:
%matplotlib inline
# 或者使用交互式后端 (更推荐)
%matplotlib widget
Matplotlib核心概念:Figure 与 Axes
理解Matplotlib的两个核心概念是绘图的关键:
- Figure (画布/画板): 这是整个绘图的容器,就像一张空白的画布。你可以在这张画布上绘制一个或多个图表。
- Axes (坐标系/子图): 这是实际绘图的区域,包含坐标轴、刻度、标签、图例等元素。一个
Figure
可以包含一个或多个Axes
。
你可以把Figure
想象成一个画廊,而Axes
就是画廊里的一幅幅画。
基本绘图流程
import matplotlib.pyplot as plt
import numpy as np# 1. 准备数据
x = np.linspace(0, 10, 100) # 从0到10生成100个均匀分布的点
y = np.sin(x) # 计算对应的sin(x)值# 2. 创建Figure和Axes对象 (推荐方式)
fig, ax = plt.subplots() # 创建一个包含单个Axes的Figure# 3. 在Axes上绘图
ax.plot(x, y) # 绘制折线图# 4. 添加标题和标签
ax.set_title("正弦函数图像")
ax.set_xlabel("x (弧度)")
ax.set_ylabel("sin(x)")# 5. 显示图表
plt.show()
代码解析:
plt.subplots()
: 这是创建Figure
和Axes
的标准方法。返回一个元组(fig, ax)
。ax.plot(x, y)
: 在ax
这个坐标系上绘制数据。x
是横坐标,y
是纵坐标。ax.set_title()
,ax.set_xlabel()
,ax.set_ylabel()
: 分别设置标题、x轴标签、y轴标签。plt.show()
: 显示最终的图表。在脚本中通常需要这一步。
绘制常见图表类型
1. 折线图 (Line Plot)
折线图用于显示数据随时间或有序类别的变化趋势。
import matplotlib.pyplot as plt
import numpy as np# 模拟股票价格数据
days = np.arange(1, 31) # 30天
np.random.seed(42)
prices = 100 + np.cumsum(np.random.randn(30)) # 累加随机数模拟价格波动fig, ax = plt.subplots(figsize=(10, 6)) # figsize设置画布大小# 绘制折线图
ax.plot(days, prices, marker='o', linestyle='-', color='blue', linewidth=2, markersize=4)# 美化图表
ax.set_title("模拟股票价格走势 (30天)", fontsize=16, fontweight='bold')
ax.set_xlabel("天数", fontsize=12)
ax.set_ylabel("价格 (元)", fontsize=12)
ax.grid(True, alpha=0.3) # 添加网格线,alpha控制透明度# 显示图表
plt.show()
关键参数:
marker
: 数据点的标记样式('o'
圆形,'s'
方形,'^'
三角形等)。linestyle
: 线条样式('-'
实线,'--'
虚线,':'
点线,'-.'
点划线)。color
: 颜色('red'
,'blue'
,'#FF5733'
十六进制,'C0'
调色板颜色)。linewidth
: 线条宽度。markersize
: 标记大小。figsize
: 以英寸为单位的画布大小(width, height)
。
2. 柱状图 (Bar Chart)
柱状图用于比较不同类别之间的数值大小。
import matplotlib.pyplot as plt# 模拟各城市销售额
cities = ['北京', '上海', '广州', '深圳', '杭州']
sales = [120, 95, 78, 110, 85]fig, ax = plt.subplots(figsize=(8, 5))# 绘制柱状图
bars = ax.bar(cities, sales, color=['skyblue', 'lightgreen', 'lightcoral', 'gold', 'plum'], alpha=0.8)# 为每个柱子添加数值标签
for bar, value in zip(bars, sales):height = bar.get_height()ax.annotate(f'{value}万',xy=(bar.get_x() + bar.get_width() / 2, height),xytext=(0, 3), # 3 points vertical offsettextcoords="offset points",ha='center', va='bottom', fontsize=10)# 美化图表
ax.set_title("各城市季度销售额对比", fontsize=14)
ax.set_xlabel("城市")
ax.set_ylabel("销售额 (万元)")
ax.set_ylim(0, max(sales) * 1.1) # 设置y轴范围,留出空间给标签
ax.tick_params(axis='x', rotation=45) # 旋转x轴标签防止重叠plt.tight_layout() # 自动调整子图参数,防止标签被截断
plt.show()
关键点:
ax.bar()
: 绘制柱状图。ax.annotate()
: 在指定位置添加文本注释,常用于在柱子顶部显示数值。plt.tight_layout()
: 非常重要!自动调整图表布局,防止标题、标签、图例等元素被截断或重叠。
3. 散点图 (Scatter Plot)
散点图用于观察两个变量之间的关系或分布模式。
import matplotlib.pyplot as plt
import numpy as np# 模拟身高和体重数据
np.random.seed(123)
heights = np.random.normal(170, 10, 100) # 均值170cm, 标准差10cm
weights = 0.8 * heights - 80 + np.random.normal(0, 5, 100) # 与身高大致线性相关,加入噪声fig, ax = plt.subplots(figsize=(8, 6))# 绘制散点图
scatter = ax.scatter(heights, weights, c=weights, cmap='viridis', alpha=0.6, s=50)
# c: 根据体重值映射颜色
# cmap: 颜色映射表 ('viridis', 'plasma', 'coolwarm'等)
# s: 点的大小# 添加颜色条 (Colorbar)
cbar = plt.colorbar(scatter)
cbar.set_label('体重 (kg)', rotation=270, labelpad=20)# 美化图表
ax.set_title("身高与体重关系散点图", fontsize=14)
ax.set_xlabel("身高 (cm)")
ax.set_ylabel("体重 (kg)")
ax.grid(True, alpha=0.3)plt.show()
关键点:
ax.scatter()
: 绘制散点图。c
: 可以让点的颜色代表第三个变量的值。cmap
: 颜色映射方案,选择合适的cmap能让图表更美观。plt.colorbar()
: 为颜色映射添加颜色条,解释颜色代表的数值。
4. 直方图 (Histogram)
直方图用于展示数值型数据的分布情况(频数或频率)。
import matplotlib.pyplot as plt
import numpy as np# 模拟考试成绩
np.random.seed(200)
scores = np.random.normal(75, 15, 200) # 均值75分, 标准差15分
scores = np.clip(scores, 0, 100) # 将成绩限制在0-100分之间fig, ax = plt.subplots(figsize=(8, 5))# 绘制直方图
n, bins, patches = ax.hist(scores, bins=15, color='steelblue', alpha=0.7, edgecolor='black')# 美化图表
ax.set_title("学生成绩分布直方图", fontsize=14)
ax.set_xlabel("成绩")
ax.set_ylabel("频数")
ax.set_xlim(0, 100)# 在每个柱子上方添加频数标签
for i in range(len(patches)):count = n[i]if count > 0: # 只为非零的柱子添加标签ax.annotate(f'{int(count)}',xy=(bins[i] + (bins[1]-bins[0])/2, count),xytext=(0, 3),textcoords="offset points",ha='center', va='bottom', fontsize=9)plt.show()
关键点:
ax.hist()
: 绘制直方图。bins
: 指定分组的数量或具体的分组边界。edgecolor
: 柱子边缘的颜色,让柱子边界更清晰。
5. 饼图 (Pie Chart)
饼图用于显示各部分占总体的比例。
import matplotlib.pyplot as plt# 模拟市场份额
companies = ['A公司', 'B公司', 'C公司', 'D公司', '其他']
market_share = [35, 25, 20, 10, 10]fig, ax = plt.subplots(figsize=(7, 7))# 绘制饼图
wedges, texts, autotexts = ax.pie(market_share, labels=companies, autopct='%1.1f%%',startangle=90, colors=['#ff9999','#66b3ff','#99ff99','#ffcc99', '#c2c2f0'])# 美化文本
for autotext in autotexts:autotext.set_color('white')autotext.set_fontweight('bold')ax.set_title("智能手机市场份额", fontsize=16, pad=20)plt.show()
关键点:
ax.pie()
: 绘制饼图。labels
: 扇形的标签。autopct
: 自动在扇形内显示百分比格式。startangle
: 饼图的起始角度。colors
: 自定义颜色。
高级技巧:在同一画布上绘制多个子图
使用plt.subplots()
可以轻松创建包含多个Axes
的Figure
。
import matplotlib.pyplot as plt
import numpy as np# 准备数据
x = np.linspace(0, 4*np.pi, 100)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = np.tan(x)
y3 = np.where(np.abs(y3) > 10, np.nan, y3) # 限制tan(x)的范围,避免线条冲出图表# 创建2x2的子图布局
fig, axes = plt.subplots(2, 2, figsize=(12, 10), constrained_layout=True)
# constrained_layout=True 是tight_layout的现代替代,效果更好# 在每个子图上绘图
axes[0, 0].plot(x, y1, 'b-', label='sin(x)')
axes[0, 0].set_title('正弦函数')
axes[0, 0].legend()
axes[0, 0].grid(True, alpha=0.3)axes[0, 1].plot(x, y2, 'r--', label='cos(x)')
axes[0, 1].set_title('余弦函数')
axes[0, 1].legend()
axes[0, 1].grid(True, alpha=0.3)axes[1, 0].plot(x, y3, 'g:', label='tan(x)')
axes[1, 0].set_title('正切函数 (截断)')
axes[1, 0].legend()
axes[1, 0].grid(True, alpha=0.3)
axes[1, 0].set_ylim(-10, 10) # 限制y轴范围# 第四个子图可以用来画一个汇总图或留空
axes[1, 1].axis('off') # 关闭第四个子图的坐标轴# 为整个画布添加一个总标题
fig.suptitle("三角函数图像对比", fontsize=18, fontweight='bold')plt.show()
与 Pandas 的完美结合
pandas
的Series
和DataFrame
提供了.plot()
方法,让你无需手动调用Matplotlib就能快速绘图。
import pandas as pd
import matplotlib.pyplot as plt# 创建一个DataFrame
data = {'Month': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],'Sales_A': [120, 135, 142, 130, 155, 168],'Sales_B': [100, 110, 105, 120, 118, 130]
}
df_sales = pd.DataFrame(data)# 设置Month为索引 (通常时间序列数据会这样做)
df_sales = df_sales.set_index('Month')# 使用pandas的plot方法 (底层是Matplotlib)
ax = df_sales.plot(kind='line', marker='o', figsize=(10, 6))
ax.set_title("A、B产品月度销售额对比")
ax.set_ylabel("销售额 (万元)")
ax.grid(True, alpha=0.3)
plt.show()# 其他类型
# df_sales.plot(kind='bar', figsize=(10, 6)) # 柱状图
# df_sales.plot(kind='barh', figsize=(8, 6)) # 横向柱状图
# df_sales['Sales_A'].plot(kind='hist', bins=5, figsize=(8, 5)) # 直方图
最佳实践与总结
- 明确目的: 在绘图前,先想清楚你想通过图表传达什么信息。
- 选择合适的图表类型: 折线图看趋势,柱状图看比较,散点图看关系,直方图看分布,饼图看比例。
- 添加清晰的标签: 标题、x轴标签、y轴标签必不可少。
- 使用图例: 当图表中有多个数据系列时,图例能帮助区分。
- 注意美观: 选择合适的颜色、字体大小,避免图表过于花哨或拥挤。
- 利用
plt.tight_layout()
或constrained_layout=True
: 这是防止布局错乱的神器。 - 保存图表: 使用
plt.savefig('my_plot.png', dpi=300, bbox_inches='tight')
保存高质量图片。bbox_inches='tight'
能确保所有元素都被包含在内。
总结
通过本课的学习,你已经成功迈出了数据可视化的第一步!你学会了:
- Matplotlib的核心概念:Figure 和 Axes。
- 使用面向对象的方法 (
fig, ax = plt.subplots()
) 进行绘图。 - 绘制折线图、柱状图、散点图、直方图、饼图等基本图表。
- 美化图表(标题、标签、图例、网格、颜色、样式)。
- 在同一画布上创建多个子图。
- 利用 Pandas 的
.plot()
方法快速绘图。
Matplotlib功能远不止于此,它还支持3D绘图、动画、更复杂的自定义等。但掌握这些基础,你已经可以应对大部分日常的数据可视化需求了。
练习建议:
- 使用上一课学生成绩分析的例子,绘制各科平均分的柱状图。
- 将天气数据(城市、温度)用柱状图或散点图表示。
- 尝试绘制你感兴趣的任何数据的图表。
- 探索不同的颜色映射 (
cmap
) 和标记样式。