☰
Pandas绘图全指南:12类基础图表用法详解
2026/9/28 15:02:20 网站建设 项目流程

Pandas 绘图这功能,用熟了你会发现它是整个数据处理链条里最被低估的一环。做数据分析的人天天跟 DataFrame 打交道,但真正到了出图环节,很多人第一反应还是打开 Matplotlib 文档抄样板代码。其实 Pandas 自带一套完整的绘图体系,df.plot() 一行就能覆盖绝大部分探索性需求。我这次直接把 12 类基础图从头到尾过一遍,从 line、bar、hist 这些日常高频图,到 scatter_matrix、parallel_coordinates 这种多变量视角,把 Pandas 里的原生绘图类型全给你捋清楚。不管你是刚入门 Pandas,还是做了几年分析想补全绘图技能树,这篇都可以当手册用。

1. Pandas 绘图值得学吗:先搞懂它的定位与 12 类图全景

1.1 为什么绘图逻辑对:少些样板代码,多些探索速度

Pandas 绘图本质上是把 Matplotlib 的绘图能力包了一层“数据友好”的外壳。DataFrame 和 Series 里的索引、列名、缺失值处理,在人类眼里是表格,在 Matplotlib 眼里是各种散装的数组,中间需要大量的坐标轴设置、图例设置、数据格式化。Pandas 把这层翻译工作直接吸收了,所以 df.plot() 才省事。

我自己判断什么时候用 Pandas 绘图,标准很简单:这张图是拿来做探索分析,还是要上会、进报告、做出版级印刷?前者一律 Pandas 绘图,后者才去精调 Matplotlib。因为探索性分析的核心诉求是“快”,你在三分钟内多画几张图,才能更快判断数据里到底有没有信号。如果每张图都从 Matplotlib 的 plt.figure() 开始撸,一顿操作下来思路都被打断了。

这里也解释一下 Pandas 绘图和 Matplotlib 的关系,不是替代而是互补。Pandas 的图后端就是 Matplotlib,两者可以混用,返回的 Axes 对象可以直接被 Matplotlib 继续修饰。这种机制决定了它不可能把所有排版功能都暴露出来,但对大多数快速看图场景已经足够了。

1.2 12 类基础图全景:哪些是原生 kind,哪些由 plotting 模块补齐

先给一张全景表,方便你对应到代码里的写法。我这里说的 12 类,是 10 种 DataFrame.plot 的 kind 参数图,加上 pandas.plotting 模块里的两个高频多变量图,这样基本覆盖了 Pandas 暴露给用户的全部原生绘图入口。

图类型调用写法典型场景
line 线图df.plot(kind='line')趋势变化、时间序列
bar 柱状图df.plot(kind='bar')分类别数值对比
barh 水平柱状图df.plot(kind='barh')类别名较长时的对比
hist 直方图df.plot(kind='hist')单变量分布形态
box 箱线图df.plot(kind='box')分位数、离群值体检
area 面积图df.plot(kind='area')多序列堆叠占比与总量
scatter 散点图df.plot(kind='scatter', x=..., y=...)两变量相关关系
pie 饼图df.plot(kind='pie')组成占比(类别少时)
hexbin 六边形图df.plot(kind='hexbin', x=..., y=...)大数据量散点密度
kde 核密度图df.plot(kind='kde')平滑分布估计
scatter_matrix 散点矩阵pandas.plotting.scatter_matrix(df)多变量两两关系
parallel_coordinates 平行坐标pandas.plotting.parallel_coordinates(df, '类别列')高维样本聚类/分类模式

这个表里的 12 类,我后文会一个一个讲清楚,包括参数、注意点和使用场景。先记住一个结论:Pandas 绘图擅长的是“数据探索期快速成图”,而不是“出版级排版”。后面遇到的具体坑,我在第 3 章逐节展开。

1.3 import 方式与版本:为什么有人写 df.plot 直接报错

有个细节很容易被忽略:新版 Pandas 中,df.plot 是 DataFrame 的内置方法,只要 import pandas 就能用。但如果你的环境里同时装了老版本 Pandas 或曾经改过 matplotlib 后端,可能会遇到 “module 'pandas' has no attribute 'plot'” 之类的问题。这个问题的常见原因,是你在没有正常导入 pandas 的情况下,调用了 pd.plot 这种容易混淆的写法。

正常情况下用 import pandas as pd,然后 df.plot() 就够了。如果图不弹出来,多半是当前 notebook 后端没选好,补充一行 %matplotlib inline(Jupyter 环境)或者 plt.show()(脚本环境)就能解决。还有一类情况是 Pandas 老版本代码里 kind='kde' 的写法现在依然兼容,但升级版本时注意看看 deprecation warning。遇到这类报错,我不建议靠记忆硬扛,直接看 warning 信息里提示的替代写法,比上网查更快。Pandas 中文文档和官方 API 参考里对这些变更记录得很清楚,画图之前先花十分钟把 df.plot? 的帮助信息拉出来扫一眼,能少踩一半坑。

2. 画图前先处理三件事:数据结构、字体和画布参数

2.1 Series 和 DataFrame:不同结构决定不同出图方式

Pandas 绘图的最小单位是 Series 和 DataFrame。Series.plot() 画出来的是单个序列的图,DataFrame.plot() 默认把每一列当成一个序列画到同一张图上,列名自动变成图例。这个区别看似简单,但很多人第一次画图就翻车:比如想画两列散点,却直接 df.plot(),出来的不是散点而是两条折线。

所以动手前先想清楚,你的数据是一个序列还是多个序列,以及目标是什么。如果是两列之间的关系,scatter、hexbin 这种图必须明确指定 x 和 y 参数。另外,Series 和 DataFrame 的索引会成为默认的 x 轴,所以索引的干净程度直接影响出图质量。常见的数据清洗工作——去重、排序、类型转换——本质上也是在为绘图铺路。比如时间列如果是字符串,画线图之前最好先 pd.to_datetime 转成时间类型,否则 x 轴顺序会按字典序排,容易画出一条乱乱的折线。

补充一个我常用的检查:df.dtypes 一定要跑一遍。如果某列显示 object 而你想画数值图,先 pd.to_numeric 或者 astype 处理掉。这是“pandas 数据类型转换”里最常被问到的绘图前置问题,比画图本身更值得花时间。数据清洗和画图不是两件事,脏数据喂进去,出来的图一样是脏的,后面第 5 章我会专门展开。

2.2 中文字体和负号显示:不配置就一团乱码

这个坑我踩了不下三次。第一次画图,标题、图例里的中文全是方块,还以为数据有问题,结果折腾半天是字体缺失。Pandas 绘图底层是 Matplotlib,Matplotlib 默认字体不包含中文字符,所以必须手动指定一个支持中文的字体。常见的配置方式是这样:

import matplotlib.pyplot as plt plt.rcParams['font.sans-serif'] = ['SimHei'] # 或者其他中文字体 plt.rcParams['axes.unicode_minus'] = False # 解决负号显示成方块的问题

第一行指定中文字体,第二行尤其容易被忽略:如果 axes.unicode_minus 保持默认 True,坐标轴的负号在部分字体渲染下会显示成一堆小方块,看起来非常业余。不同系统的字体名不一样,Windows 常用 SimHei / Microsoft YaHei,macOS 可以用 PingFang SC 或 Arial Unicode MS,Linux 可以装文泉驿或 Noto Sans CJK。配置之后如果还是乱码,可以先用下面这段代码查一下当前环境中到底有哪些可用字体:

import matplotlib.font_manager as fm fonts = [f.name for f in fm.fontManager.ttflist if 'CJK' in f.name or 'Hei' in f.name or 'Song' in f.name] print(set(fonts))

这段输出会告诉你该填哪个字体名。注意字体名和字体文件路径是两回事,我试过直接把 .ttf 路径填进 rcParams,结果完全不生效。

2.3 figsize、subplots 和 layout:先规划好画布再动手

画布尺寸这种事,晚调不如早调。如果你一开始就用默认尺寸画多列数据,后面再改 figsize,往往要重新调整字体、图例位置,返工成本很高。Pandas 绘图里 figsize 可以直接传进 plot 方法:

df.plot(kind='line', figsize=(10, 5))

另一个高频参数是 subplots。当 DataFrame 有多列,而且你想把它们拆成上下多个小图时,subplots=True 非常省事:

df.plot(kind='line', subplots=True, layout=(3, 1), figsize=(8, 10))

layout 控制几行几列,sharex 和 sharey 可以控制子图之间是否共享坐标轴。这里我建议一上来就把 figsize 按内容量估准,宁可偏大不要偏小,后面做标注、加注释时空间才够用。画多图对比时,把相关的序列放在同一个子图里比拆成多个子图更适合看相关性,这个后面第 4 章还会继续讲。

3. 12 类基础图逐个拆解

3.1 line 线图:默认图表,先看数据点玩的是趋势

line 图是 Pandas 绘图的默认类型,df.plot() 不带任何 kind 参数时画的就是它。数据里只要是带顺序的索引(时间、步数、排名),我都会先画一张 line 看整体走势。最简单的用法:

import pandas as pd import numpy as np np.random.seed(42) idx = pd.date_range('2024-01-01', periods=100, freq='D') df = pd.DataFrame({'销量': np.random.randint(50, 200, size=100)}, index=idx) df.plot(figsize=(10, 4))

默认情况下,DataFrame 的索引会成为 x 轴,列名成为图例。这个行为很省心,但也容易埋坑:如果索引没有排序,画出来的线会来回折返,像一团乱麻。尤其是做时间序列时,我总会先 df.sort_index() 再画。另一个常用参数是 marker,想强调数据点时可以 df.plot(marker='o'),但数据点非常多时建议去掉 marker,否则图会显得很脏。

如果 DataFrame 有多列,默认会把所有列画到同一张图上,而且 y 轴量纲不同时会互相压缩。比如一列是销量(几十到几百),一列是单价(几块钱),两者画在一起,销量会把单价压成一条近似水平的直线。这时候我的经验是:要么先标准化,要么 subplots=True 拆开画。

注意:line 图对缺失值很敏感。如果序列里有 NaN,Matplotlib 默认会跳过该点,线会断掉。要保留连接线,可以先 df.interpolate() 补上再画,否则出图的连续性会误导判断。

3.2 bar 柱状图:分类别数值对比

bar 图适合表达“类别到数值”的对比。在 Pandas 里,bar 的 x 轴来自 DataFrame 的索引,所以通常先把要对比的类别放到索引上:

sales = pd.Series({'华东': 120, '华南': 90, '华北': 110, '西南': 70}) sales.plot(kind='bar', figsize=(8, 4))

如果传入的是 DataFrame,每一列会变成一组柱子,图例会按列名展示。想改成横向对比,用 barh 就行。barh 在类别名很长时特别友好,比如省份名称、产品型号,横着放标签不会被截断。

柱状图有两个高频参数值得留意:stacked 和 color。stacked=True 可以把多列堆叠起来,看的是总量加构成;color 传入一个列表可以直接指定每列颜色。由于 Pandas 默认按列名自动分配颜色,如果你对色板有要求,建议提前定义好颜色列表,而不是画完再一根根改。

实操里我发现 bar 和 barh 的顺序问题比想象中常见。默认柱子顺序跟索引顺序一致,如果索引是字符串,会按字典序排列,往往不是你期望的业务顺序。解决办法是用 pd.Categorical 或者 reindex 手动排好序。这一步在画图之前做,比画完再用 Matplotlib 的 tick 调整要干净得多。

3.3 hist 直方图:用 bins 控制分箱粒度

hist 是单变量分布的一线侦察兵。一句话说清原理:把数值范围切成若干区间,然后数每个区间里有多少样本,柱子的高度就是这个区间内的样本数。bins 参数决定切多少份,这个数直接决定图的信息粒度。

df['销量'].plot(kind='hist', bins=20, figsize=(8, 4))

bins 太小时,分布的形状会被抹平,看不出峰和谷;bins 太大时,噪音会被放大,依然呈现锯齿状。我的经验是,先试 bins=30 看整体,再根据数据量调整。数据量几千条时 20-50 都合理,几万条以上可以尝试更多分箱。

DataFrame 多列也可以一起画 hist,默认会重叠在一起,容易看不清。这时用 subplots=True 拆成多个小图,或者给每列设置 alpha=0.5 半透明叠加。直方图很容易让人误判双峰分布,其实可能是两个不同来源的数据混在一起。遇到这种形态,我会先把数据按某个分组维度分开再画一次,往往会有新发现。

3.4 box 箱线图:一组数字的体检报告

box 图会一次性展示中位数、四分位数、四分位距和离群点,相当于给数值列做体检。你的数据里如果存在明显的离群点,通过 box 一眼就能定位到是哪几条记录把分布拖偏了。

df[['销量', '单价', '库存']].plot(kind='box', figsize=(8, 5))

如果 DataFrame 有多个数值列,box 会把每一列当成一个箱子横着排出来,方便比较不同列的分布。还有一个好用的是 by 参数,能按某个分类列把箱线图分组:

df.plot(kind='box', by='区域', figsize=(10, 5))

这个写法会把每个分类下的分布并排展示,非常适合“不同区域的销量差异”这类问题。我拿到新数据做体检时,通常会先画一个全数值列的 box,看到哪个箱子的离群点特别多,再去翻原始数据,效率比肉眼扫表高很多。

注意:box 图对异常值的容忍度很高,但这不代表你应该忽略它们。画完 box 后,可以再用 df[df['销量'] > 上界] 把离群点挑出来看,通常能发现数据采集错误或业务上的特殊事件。

3.5 area 面积图:堆叠趋势一眼看全

area 图可以理解为“填了颜色的 line 图”,默认还会把多条序列堆叠起来。堆叠后不但能看到每条序列自己的趋势,还能看到总量和占比的演化,适合看三个月内各渠道的流量贡献:

df[['A渠道', 'B渠道', 'C渠道']].plot(kind='area', figsize=(10, 5))

Pandas 的 area 图默认 stacked=True,也就是堆叠模式。如果多条序列量级差异太大,堆叠后的小序列几乎会被大序列压扁,这时要么分开画,要么先做归一化。另一个容易踩的坑是 area 图对索引顺序要求高,索引乱序会造成填充区域乱交叉。所以画 area 前,我会先确认索引有序并且类型正确。

我自己的习惯是:看总量变化用堆叠 area,想看各序列自身趋势时关闭堆叠(stacked=False),再加一点透明度。切记不要把颜色配得太深,否则多个区域叠在一起会变成一团黑,信息反而丢了。

3.6 scatter 散点图:两变量相关性的第一印象

scatter 图是探索两列关系的默认答案。它必须显式指定 x 和 y:

df.plot(kind='scatter', x='广告投入', y='销量', figsize=(8, 6))

散点图最大的价值是让你在算相关系数之前,先肉眼看清楚两个变量的关系形态。线性相关、非线性、异方差性、甚至离群点,在散点图上一目了然。如果点非常多,可以用 alpha 参数降低透明度,避免一个黑坨;也可以用 c 参数按第三列着色,比如点的颜色代表另一个维度,这样散点图就从二维关系扩容成三维甚至四维信息。

这里我要强调一下:Pandas 散点图的 x 和 y 参数是必须的。如果你直接 df.plot(kind='scatter'),大部分情况下会直接报错,因为 Pandas 不知道拿哪两列去画。这是新手最常见的一个报错场景,后面第 5 章我整理了一张速查表,可以直接对着排查。

3.7 pie 饼图:能用但别滥用

pie 在 Pandas 里的写法很简单,但限制也最明显:它通常只接受 Series,不接受 DataFrame 太多列。Pandas 会按索引作为扇区标签,按值作为占比。用法如下:

sales = pd.Series({'华东': 120, '华南': 90, '华北': 110}) sales.plot(kind='pie', autopct='%.1f%%', figsize=(6, 6))

如果你把 DataFrame 直接传给 kind='pie',Pandas 会尝试为每一列画一张饼图,大概率不是你想要的结果。而且饼图的扇区太多时很难看,超过 5 到 7 个类别,我建议大家换 bar 或者 barh。饼图的比较精度也很差,人类对角度的感知远不如对长度的感知,这也是我日常几乎只用它做“整体构成展示”的原因。

3.8 hexbin 六边形图:大数据量散点的救星

当散点多到几万、几十万时,scatter 画出来的基本是一团黑,完全看不到密度分布。hexbin 把二维平面切成很多小六边形,统计每个格子里的样本数,再用颜色深浅表示密度,相当于散点图的“密度热点图”:

df.plot(kind='hexbin', x='x列', y='y列', gridsize=20, figsize=(8, 6))

gridsize 控制六边形网格的密度,越小颜色块越粗,越大越细腻。实际使用中,几十万行数据用 hexbin 画起来,流畅度和清晰度都远胜 scatter。如果你发现 hexbin 图例上的颜色条默认位置不顺手,可以用 Matplotlib 的 colorbar 方法调整,这类细节可以放在第 4 章统一处理。

注意:hexbin 需要的数据格式是两列数值型数据,如果有缺失值,Pandas 会自动跳过包含 NaN 的行,这是它底层实现的行为。你不需要手动 dropna,但前提是缺失值占比不能太高,否则图会失去代表性。

3.9 kde 核密度图:比直方图更平滑的分布线

kde(也叫 density)图可以看作直方图的“平滑连续版”。它不是把数据切成箱子,而是用核函数给每个样本周围铺一条“概率密度山包”,叠加起来形成一条平滑的密度曲线:

df['销量'].plot(kind='kde', figsize=(8, 4))

当你想比较两组数据分布的形状差异时,kde 比 hist 更直观,因为多条密度曲线可以清晰地叠在一起而不互相遮挡。bw_method 参数控制曲线的平滑程度,值越小曲线越贴近原始数据,越大越平滑。我的经验是先用默认值,如果曲线锯齿感强就适度调大;如果被抹平到看不出峰,就调小。

kde 和 hist 不是替代关系。我会先用 hist 看原始柱状形态,再用 kde 确认平滑后的趋势。如果两个峰在 hist 中清晰可见,kde 中却变成一个缓坡,那很可能是样本量太少或者带宽设置偏大,需要回退检查数据量和参数。

3.10 scatter_matrix 散点矩阵:多变量两两关系一眼扫完

scatter_matrix 属于 pandas.plotting 模块,不是 DataFrame.plot 的 kind,但画起来同样是一行代码:

from pandas.plotting import scatter_matrix scatter_matrix(df[['销量', '单价', '库存']], alpha=0.5, figsize=(10, 10), diagonal='hist')

它的输出是一个矩阵:对角线位置画每个变量的分布(默认是直方图,也可以改成核密度估计或箱线图),非对角线位置画两两变量的散点图。这个图在做数据探索初期非常高效,一口气能看得出哪些变量之间可能有线性关系、哪些变量是偏态分布、哪些组合有明显离群点。

数据列数多时,我不会把所有列都丢进去,一般选 4 到 6 个核心变量,否则矩阵会大到看不清。diagonal 参数是我最常用的:diagonal='hist' 让对角线看分布,diagonal='kde' 看平滑密度。scatter_matrix 返回的是一个 Axes 的二维数组,后面想做局部调整可以直接按索引定位。

3.11 parallel_coordinates 平行坐标:高维数据的全貌视图

平行坐标适合看“高维样本在类别之间的分离模式”。每个样本用一条折线串过所有特征,颜色按分类列标记。如果某个类别在某一列上明显偏移,折线束会呈现“分叉”形态,特征列的作用就一下看出来了:

from pandas.plotting import parallel_coordinates parallel_coordinates(df[['销量', '单价', '库存', '区域']], class_column='区域', colormap='Set1', figsize=(10, 5))

注意这里必须指定 class_column,也就是用来分组的类别列,否则函数不知道按什么着色。平行坐标对特征量纲很敏感,如果一列动辄上千、另一列只有个位数,小量纲列会被压平。我的习惯是先用 sklearn 的 StandardScaler 或者 Pandas 的 (df - df.mean()) / df.std() 做标准化,再看类别分叉。

3.12 12 类之外的补充:绘图函数里还藏着几个彩蛋

到这里,12 类基础图已经全部过了一遍:前 10 种是 DataFrame.plot 的 kind,后 2 种是 pandas.plotting 的高频函数。如果你还想往深处挖,pandas.plotting 里其实还藏着 radviz、lag_plot、autocorrelation_plot、bootstrap_plot 这类不那么常用但偶尔能救命的图。lag_plot 看时间序列的自相关趋势,autocorrelation_plot 直接给出各滞后阶数的自相关系数,bootstrap_plot 可以快速评估统计量的稳定性。

这些图我平时用得少,但遇到时间序列数据时,autocorrelation_plot 是判断“这列数据到底有没有周期惯性”的最快手段。写法同样是一行:

from pandas.plotting import autocorrelation_plot autocorrelation_plot(df['销量'])

所以 12 类基础图只是 Pandas 绘图能力的一个骨架,骨架之上还藏着一层扩展。第 5 章我会专门讲怎么灵活组合它们。

4. 样式控制与导出:从能画到画得能看

4.1 图例、颜色和网格:三个最常调的细节

Pandas 绘图的默认样式偏“裸奔”,离能见人的图还差几步。我每次画完图,第一件事就是看三样:图例位置、颜色搭配、网格线。图例默认位置由 Matplotlib 决定,经常挡住数据线。用 legend=False 关掉 Pandas 自带的图例,再手动调用 ax.legend(loc='best' 或 'upper left') 来控制。颜色建议在调色板里挑一组视觉友好的,不要用默认循环色硬凑。网格线用 ax.grid(True, linestyle='--', alpha=0.6)。

这里有一个技巧:所有 Pandas 图方法都返回 Axes 对象,你可以把返回值存下来再继续修饰:

ax = df.plot(kind='bar', title='各区域销量对比') ax.set_xlabel('区域') ax.set_ylabel('销量') ax.grid(True, linestyle='--', alpha=0.6)

这样既保住了 Pandas 的省事,又拿到了 Matplotlib 的灵活性。

4.2 subplots 布局与共享坐标轴

当你要画多张图并排对比时,可以灵活使用 subplots、layout 和 sharex。subplots=True 会把 DataFrame 的每一列画到独立的小图,layout=(2,2) 控制几行几列。sharex=True 和 sharey=True 可以让坐标轴对齐,方便比较不同子图的趋势和量级。

不过我的实际经验是,多序列对比时,把不同序列画在同一个子图里往往更容易看出相对关系;子图更适合量纲相差过大或者类别语义不同的列。比如历史销量和当天销量可以放一张图,销量和库存就应该拆开,因为它们单位不同、业务含义也不同。

4.3 保存图片:dpi、bbox_inches 和 format

Pandas 绘图本身不直接提供 savefig 参数,但返回的 Axes 可以拿到对应的 Figure:

import matplotlib.pyplot as plt ax = df.plot(kind='line', figsize=(10, 5)) fig = ax.get_figure() fig.savefig('sales_trend.png', dpi=300, bbox_inches='tight')

dpi=300 是报告和展示的基本要求,bbox_inches='tight' 可以自动裁掉多余白边。这里还有个容易踩的坑:保存前最好调用 plt.tight_layout(),否则标题可能被截掉。有的朋友会直接用 plt.savefig,也能用,但我更推荐 ax.get_figure().savefig,这样明确保存的是当前这张图,不容易把之前 notebook 里的其他图也一起覆盖。

5. 常见问题与排查技巧实录

5.1 一张表搞定最常见的 8 个报错和异常

问题表现原因解决方案
kind='scatter' 报错没传 x 和 ydf.plot(kind='scatter', x='列A', y='列B')
kind='pie' 报错或图太乱传入了 DataFrame 多列改成 Series.plot(kind='pie')
中文全是方块中文字体未配置配置 plt.rcParams['font.sans-serif']
负号全是方块axes.unicode_minus 默认设置 plt.rcParams['axes.unicode_minus'] = False
图不显示非 notebook 环境没调用 plt.show()脚本末尾加 plt.show()
hexbin 图空白x/y 列有大量 NaN先 dropna 或确认数据量
line 图折线乱飞索引没有排序df.sort_index() 后再画
多列 y 轴互相挤压量纲差异太大subplots=True 拆图或先标准化

这些报错我自己基本都踩过一遍,每个都是几分钟可以解决的问题,但第一次碰上确实容易愣住。把这张表保存在手边,比临时翻报错堆栈效率高很多。

5.2 数据清洗与绘图的关系:脏数据画出来的图也脏

很多人把数据清洗和绘图分开看待,其实两者密不可分。一个典型场景:销量列是字符串 “1,234”,Pandas 会把它识别成 object,画出来的图要么报错要么全是乱码。这时候必须先做类型转换:

df['销量'] = pd.to_numeric(df['销量'].str.replace(',', ''), errors='coerce')

还有缺失值。画 box 前你不 dropna 也不一定报错,但图里的统计结果会受影响。重复行在聚合类图表里会造成虚高,画柱状图前最好先 df.drop_duplicates()。这些事不是绘图方法本身能解决的,必须在进入画图环节之前处理好。我写这份手册时,特别在第 2 章强调数据结构,就是因为画图翻车的原因大概率都在数据侧,而不是 Pandas 侧。

5.3 大数据量绘图卡顿:先用采样和分箱

几十万行的 DataFrame 画散点或者线图,即便能出图也会卡到想砸电脑。我自己的处理策略有三个:散点图改用 hexbin,速度快且信息密度高;线图按时间降采样,比如从逐小时变成逐日,用 resample('D').mean() 聚合一下,趋势不会丢,点却少很多;如果不适合聚合,可以用 df.sample(n=50000, random_state=42) 随机抽样后画图,先看个大概。

还有一个很多人忽略的点:图形加载慢不全是数据行数的问题,也可能是字体加载和环境渲染的问题。在 Web 端 notebook 里画大图尤其明显。遇到卡顿别硬等,先去数据量上想办法,效果立刻不同。

5.4 直接调 Matplotlib:什么时候 Pandas 绘图满足不了你

Pandas 绘图给你的是“快速达成”的路径,但它不会给你完整的出版级控制力。需要用到复杂多子图自由布局、坐标轴刻度精细定制、自定义图例形状、动画或交互式图表时,还是得直接用 Matplotlib 或更上层的库(比如 plotly、seaborn)。我的经验是,先想清楚这张图的核心目的是探索还是交付,再决定用哪一层工具。

比如 Seaborn,本质上是另一个封装 Matplotlib 的库,在统计绘图的默认样式和高级聚合上做得比 Pandas 更细。但 Pandas 的好处是你不用额外处理 DataFrame 格式,直接 df.plot() 就能跑通。所以我在实际项目里的流程通常是:数据整理,Pandas plot 快速出草图,有必要的图再换 Seaborn 或 Matplotlib 精修。这套流程能帮你省下至少一半的返工时间。

最后再分享一个我自己很受用的小技巧:Pandas 绘图所有方法都返回 Axes 对象,这意味着你不必在“Pandas 绘图”和“Matplotlib 精修”之间二选一。我通常先用 df.plot() 快速出图确认方向和结论,再用返回的 ax 对象去调 xlabel、ylabel、legend、grid 这些细节;只有特别重要的图才整体迁移到 Seaborn 或 Matplotlib。12 类图你不要想着一天全背下来,先用 line、bar、hist、scatter 这四类把日常问题覆盖住,用到其他图时再回翻这份手册。等哪天真碰到几万行以上的散点图,你会感谢自己当初多看了一眼 hexbin。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询