为什么数据可视化是数据分析的最后一公里

做数据分析的人都知道一句话:表格告诉你数字,图表告诉你故事。同一组数据,放在 Excel 表格里是几十个数字,画成折线图之后趋势一眼就能看出来——哪一年涨得快、哪一个点是异常值、两条线什么时候交叉,全部变成视觉直觉。这就是数据可视化的价值:把抽象数据变成人脑能直接理解的图形。

Python 生态里做可视化最常用的两个库是 Matplotlib 和 Plotly。Matplotlib 是老牌静态图库,画出来的图是 PNG 或 PDF 图片,适合放报告和论文;Plotly 是交互式图库,画出来的图可以鼠标悬停看数值、缩放、切换显示隐藏,适合做网页仪表盘和探索性分析。两个库不是竞争关系,而是互补——出报告用 Matplotlib,做交互分析用 Plotly。

选择工具的原则:需要发给别人看的静态图用 Matplotlib,需要自己探索或嵌网页的图用 Plotly。
本文核心知识点
  • MatplotlibPython 最基础的绘图库,生成静态位图。
  • Plotly交互式可视化库,支持悬停、缩放、联动。
  • 图表类型柱状、折线、散点、饼图、热力图各有适用场景。
  • 选型报告论文用 Matplotlib,网页仪表盘用 Plotly。
Python 数据可视化示意:蓝色渐变背景上柱状图和折线图从数据管线中升起,旁边漂浮仪表盘和饼图面板
数据从数据库流出,经过清洗和聚合,最终变成柱状图、折线图和饼图——这就是数据可视化的完整链路。

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() 自动调整间距,防止标题和标签重叠。中文字体那两行必须加,否则中文显示成方块。