为什么数据可视化是数据分析的最后一公里
做数据分析的人都知道一句话:表格告诉你数字,图表告诉你故事。同一组数据,放在 Excel 表格里是几十个数字,画成折线图之后趋势一眼就能看出来——哪一年涨得快、哪一个点是异常值、两条线什么时候交叉,全部变成视觉直觉。这就是数据可视化的价值:把抽象数据变成人脑能直接理解的图形。
Python 生态里做可视化最常用的两个库是 Matplotlib 和 Plotly。Matplotlib 是老牌静态图库,画出来的图是 PNG 或 PDF 图片,适合放报告和论文;Plotly 是交互式图库,画出来的图可以鼠标悬停看数值、缩放、切换显示隐藏,适合做网页仪表盘和探索性分析。两个库不是竞争关系,而是互补——出报告用 Matplotlib,做交互分析用 Plotly。
选择工具的原则:需要发给别人看的静态图用 Matplotlib,需要自己探索或嵌网页的图用 Plotly。
- MatplotlibPython 最基础的绘图库,生成静态位图。
- Plotly交互式可视化库,支持悬停、缩放、联动。
- 图表类型柱状、折线、散点、饼图、热力图各有适用场景。
- 选型报告论文用 Matplotlib,网页仪表盘用 Plotly。
Matplotlib 基础:从零画一张图
安装 Matplotlib 只需要一条命令:pip install matplotlib。它和 pandas 配合得非常好——DataFrame 直接调用 .plot() 就能画图。先看一个最简单的例子:
import matplotlib.pyplot as plt
x = [1, 2, 3, 4, 5]
y = [2, 4, 1, 5, 3]
plt.plot(x, y)
plt.title("简单折线图")
plt.xlabel("X 轴")
plt.ylabel("Y 轴")
plt.savefig("line.png", dpi=150)
plt.show()
这段代码做了五件事:准备数据、画图、加标题、加坐标轴标签、保存为 PNG。plt.plot() 默认画折线图,savefig 把图存到文件,dpi=150 控制分辨率——报告里用 150 够清晰,网页上用 100 就够。
在 Jupyter Notebook 里画图更方便,加一行 %matplotlib inline 图表就直接嵌在笔记本里,不用 savefig。
常见图表类型:柱状、折线、散点、饼图
不同数据适合不同图表。选错了图表类型,就像穿错了鞋——不是不能走,但是不舒服。下表是最常用的四种图表和各自的适用场景:
| 图表类型 | 适用场景 | Matplotlib 函数 |
|---|---|---|
| 折线图 | 时间序列趋势变化 | plt.plot() |
| 柱状图 | 分类数据对比 | plt.bar() |
| 散点图 | 两个变量的相关性 | plt.scatter() |
| 饼图 | 部分占整体的比例 | plt.pie() |
import matplotlib.pyplot as plt
# 柱状图:各季度销售额
quarters = ["Q1", "Q2", "Q3", "Q4"]
sales = [120, 180, 150, 220]
plt.bar(quarters, sales, color="#1E5FA8")
plt.title("季度销售额对比")
plt.ylabel("销售额(万元)")
plt.savefig("bar.png", dpi=150)
# 散点图:身高与体重
import random
heights = [random.randint(150, 190) for _ in range(50)]
weights = [h - 105 + random.randint(-10, 10) for h in heights]
plt.scatter(heights, weights, alpha=0.6)
plt.title("身高与体重关系")
plt.xlabel("身高(cm)")
plt.ylabel("体重(kg)")
plt.savefig("scatter.png", dpi=150)
散点图里的 alpha=0.6 是透明度——数据点重叠时半透明才能看出密度。柱状图的 color="#1E5FA8" 指定了柱子颜色,不传的话用默认蓝色。
样式与子图:让图表更好看
默认画出来的图比较朴素。要提升可读性,有几个常用技巧:设置中文字体避免方块、加网格辅助读数、用子图把多张图拼在一起。
import matplotlib.pyplot as plt
# 设置中文字体(Windows)
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 2x2 子图画布
fig, axes = plt.subplots(2, 2, figsize=(10, 8))
# 左上:折线
axes[0, 0].plot([1, 2, 3, 4], [2, 4, 1, 5])
axes[0, 0].set_title("折线图")
# 右上:柱状
axes[0, 1].bar(["A", "B", "C"], [3, 7, 5])
axes[0, 1].set_title("柱状图")
# 左下:散点
axes[1, 0].scatter([1, 2, 3, 4], [3, 1, 4, 2], s=50)
axes[1, 0].set_title("散点图")
# 右下:饼图
axes[1, 1].pie([30, 45, 25], labels=["一类", "二类", "三类"])
axes[1, 1].set_title("饼图")
plt.tight_layout()
plt.savefig("subplots.png", dpi=150)
plt.subplots(2, 2) 创建了一个 2 行 2 列的画布,返回的 axes 数组用行列索引定位每个子图。tight_layout() 自动调整间距,防止标题和标签重叠。中文字体那两行必须加,否则中文显示成方块。
Plotly 入门:从静态到交互
Matplotlib 画的是死图——你看到什么就是什么,不能放大不能悬停。Plotly 画的是活图——鼠标移上去显示数值框、滚轮缩放、点击图例切换显示隐藏。安装:pip install plotly。
import plotly.express as px
# 用内置数据集画交互式散点图
df = px.data.iris()
fig = px.scatter(
df, x="sepal_width", y="sepal_length",
color="species", size="petal_length",
title("鸢尾花特征分布"
)
fig.show()
fig.write_html("scatter.html")
这段代码用 Plotly 内置的鸢尾花数据集画了一张散点图。color="species" 按品种上色,size="petal_length" 让点的大小随花瓣长度变化。fig.show() 在浏览器里打开交互窗口,write_html 把图存成一个独立的 HTML 文件——这个文件可以直接发给别人,打开就能交互,不需要装 Python。
Plotly Express 是高层 API,几行代码就能出图;更精细的控制用 plotly.graph_objects,可以逐元素指定颜色、线宽、标注。
Plotly 进阶:交互式仪表盘
Plotly 真正强大的地方是做交互式仪表盘。用 make_subplots 可以把多张图拼在一个面板里,加上下拉菜单和滑块就能做动态筛选。
from plotly.subplots import make_subplots
import plotly.graph_objects as go
import plotly.express as px
df = px.data.gapminder()
china = df[df.country == "China"]
fig = make_subplots(
rows=1, cols=2,
subplot_titles=("人口变化", "GDP 变化")
)
fig.add_trace(
go.Scatter(x=china.year, y=china.pop, name="人口"),
row=1, col=1
)
fig.add_trace(
go.Scatter(x=china.year, y=china.gdpPercap, name="人均GDP"),
row=1, col=2
)
fig.update_layout(title_text="中国发展指标仪表盘", showlegend=False)
fig.write_html("dashboard.html")
这段代码用 Gapminder 数据集做了一个双图仪表盘:左图看人口变化,右图看人均 GDP 变化。生成的 HTML 文件里两张图可以各自缩放,鼠标悬停显示具体年份和数值。
实际项目中,仪表盘的数据通常来自数据库查询,把查询结果传给 Plotly 再 write_html 或直接嵌进 Flask/Django 页面,就是一个完整的数据看板。
选型建议:Matplotlib 还是 Plotly
两个库怎么选,看你的使用场景:
- 写论文、做 PPT、出报告:用 Matplotlib。它生成的图片分辨率可控、样式严谨,是学术出版的标准。
- 做网页仪表盘、交互式分析、探索性数据探索:用 Plotly。交互体验远超静态图,用户可以自己放大、筛选、切换视角。
- 快速出图验证想法:两个都行。pandas 的
.plot()底层就是 Matplotlib,一行代码出图最快。
还有一个折中方案:用 Seaborn(基于 Matplotlib 的高级封装)画统计图表,样式比原生 Matplotlib 好看很多,默认配色更现代。需要交互时再换 Plotly。
数据可视化的目标是让读者快速理解数据,工具只是手段——先想清楚要表达什么,再选图表类型和工具。