目录导航
- 1Matplotlib 基础:架构、画布与坐标系、常用配置
- 2常用图表:折线、柱状、散点、饼图、直方图、箱线图、热力图、子图
- 3样式美化:颜色、图例、注释、刻度、中文字体
- 4Seaborn:统计图表、调色板、FacetGrid、样式主题
- 5Pandas 绘图:一行代码画图、多 DataFrame 叠加
- 6Plotly 交互图表:交互式折线/散点/3D、Express 快速绘图
- 7图表选型指南:什么数据用什么图
- 8实战技巧与常见坑:中文乱码、保存 DPI、动画、大屏配色
一、Matplotlib 基础
Matplotlib 是 Python 最基础的绑图库,其他库(Seaborn、Pandas.plot)都基于它构建。
两种绘图方式
① pyplot 状态机接口:类似 MATLAB,快速上手。
② 面向对象接口(推荐):通过 fig / ax 对象操作,结构清晰,适合多子图。
核心概念
| 概念 | 含义 |
|---|---|
Figure | 画布(整个窗口) |
Axes | 坐标系(一张子图) |
Axis | 坐标轴(x/y 轴对象) |
Artist | 一切可见元素(文字、线、图例…) |
基本绘图流程(面向对象方式)
import numpy as np import matplotlib.pyplot as plt x = np.linspace(0, 2*np.pi, 100) # 1. 创建画布与坐标系 fig, ax = plt.subplots(figsize=(8, 5), dpi=100) # 2. 绘制数据 ax.plot(x, np.sin(x), label='sin(x)', color='tab:blue', linewidth=2, linestyle='--') ax.plot(x, np.cos(x), label='cos(x)', color='tab:red', linewidth=2) # 3. 添加图表元素 ax.set_title('三角函数曲线', fontsize=14) ax.set_xlabel('x 弧度'); ax.set_ylabel('y 值') ax.legend(loc='upper right') # 图例 ax.grid(True, alpha=0.3) # 网格线 ax.set_xlim(0, 2*np.pi) # 坐标范围 # 4. 显示 / 保存 plt.tight_layout() # 自动调整布局防重叠 plt.savefig('fig.png', dpi=300, bbox_inches='tight') plt.show()
常用 rcParams 全局配置
# 解决中文乱码 + 负号显示问题(必备!) plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei'] # Windows # Mac 用 ['PingFang SC', 'Heiti TC'];Linux 可用 'WenQuanYi Micro Hei' plt.rcParams['axes.unicode_minus'] = False plt.rcParams['figure.dpi'] = 100 # 全局分辨率 plt.rcParams['font.size'] = 11 # 全局字号 plt.rcParams['axes.grid'] = True # 默认显示网格
提示:查看系统可用中文字体:
[f.name for f in plt.font_manager.fontManager.ttflist]二、常用图表类型
Matplotlib 八大常用图表速查,含关键参数。
📈 折线图 plot()
ax.plot(x, y,
color='red', # 颜色
linewidth=2, # 线宽
linestyle='--', # 线型 '-' '--' '-.' ':'
marker='o', # 标记 o s ^ * D v
markersize=6,
alpha=0.8, # 透明度
label='图例名')
📊 柱状图 bar() / 横向 barh()
ax.bar(categories, values,
width=0.6, # 柱宽
color='steelblue',
edgecolor='black',
hatch='//') # 填充纹理
ax.bar_label(bars, padding=3) # 柱顶标数值
# 分组柱状图:错开 x 位置
ax.bar(x - w/2, g1, width=w, label='A')
ax.bar(x + w/2, g2, width=w, label='B')
🔵 散点图 scatter()
sc = ax.scatter(x, y,
s= sizes, # 点面积(可传数组)
c= values, # 颜色映射值
cmap='viridis', # 颜色映射方案
alpha=0.6, # 半透明防遮挡
edgecolors='w')
fig.colorbar(sc, label='数值')
🥧 饼图 pie()
ax.pie(values, labels=labels,
autopct='%.1f%%', # 显示百分比
startangle=90, # 起始角度
explode=[0.1, 0, 0, 0], # 突出某块
shadow=True,
colors=colors)
ax.axis('equal') # 保证是正圆
📶 直方图 hist()
ax.hist(data, bins=30, # 分箱数 density=True, # 归一化为概率密度 cumulative=True, # 累积分布 color='skyblue', edgecolor='white')
📦 箱线图 boxplot() / 小提琴图
ax.boxplot(data_list, labels=names,
patch_artist=True, # 填充颜色
showmeans=True, # 显示均值
vert=True)
# 小提琴图(分布+密度)
ax.violinplot(data_list, showmedians=True)
🌡️ 热力图 imshow()
im = ax.imshow(corr_matrix,
cmap='RdBu_r', vmin=-1, vmax=1)
fig.colorbar(im)
ax.set_xticks(range(n), labels, rotation=45)
ax.set_yticks(range(n), labels)
# 在格子里写数值
for i in range(n):
for j in range(n):
ax.text(j, i, f'{corr[i,j]:.2f}',
ha='center', va='center')
🔲 填充图 fill_between()
# 两曲线间填充(常用于置信区间) ax.fill_between(x, y1, y2, color='blue', alpha=0.2) # 曲线下面积 ax.fill_between(x, y, 0, where=(y > 0), interpolate=True)
子图布局(重点)
# 方式1:subplots 一次创建多个坐标系(推荐) fig, axes = plt.subplots(2, 2, figsize=(10, 8)) # 2行2列 axes[0,0].plot(x, y) # 注意 axes 是二维数组 axes[0,1].bar(cx, cy) axes[1,0].scatter(sx, sy) axes[1,1].hist(h) fig.suptitle('多子图总标题') plt.tight_layout() # 方式2:add_gridspec 不规则布局 fig = plt.figure(figsize=(8, 6)) gs = fig.add_gridspec(2, 3) ax1 = fig.add_subplot(gs[0, :]) # 第一行占满3列 ax2 = fig.add_subplot(gs[1, 0]) ax3 = fig.add_subplot(gs[1, 1:]) fig.subplots_adjust(hspace=0.4, wspace=0.3) # 方式3:共享坐标轴 fig, axes = plt.subplots(2, 1, sharex=True, sharey=False) # 方式4:双 y 轴 ax2 = ax1.twinx() # 共用x轴、独立y轴
三、样式美化
让图表更专业的关键配置。
常用颜色写法
# 单色 'r' 'g' 'b' 'k' # 缩写 'tab:blue' 'tab:orange' # 官方默认10色 '#FF5733' # 十六进制 'steelblue' 'crimson' # CSS色名 (0.2, 0.4, 0.6) # RGB元组 # 颜色循环 plt.rcParams['axes.prop_cycle'] = plt.cycler( color=plt.cm.Set2.colors)
常用 cmap 色图
| 场景 | 推荐 cmap |
|---|---|
| 顺序数据 | viridis / Blues / YlOrRd |
| 发散数据(有正负) | RdBu_r / coolwarm / seismic |
| 分类数据 | Set2 / tab10 / Paired |
注意:热力图勿用彩虹色
jet(视觉误导),推荐 viridis。注释、图例与刻度
# 文字注释 ax.text(x, y, '文本', fontsize=10, color='gray', ha='center') # 箭头注释(标注最大值点) ax.annotate('最大值', xy=(xmax, ymax), xytext=(xmax, ymax+1), arrowprops=dict(arrowstyle='->', color='red')) # 图例 ax.legend(loc='best', frameon=False, ncol=2, fontsize=9) # loc: best upper/lower left/right/center # 刻度控制 ax.tick_params(axis='x', rotation=45, labelsize=9) ax.set_xticks([...], labels=[...]) # 自定义刻度 ax.xaxis.set_major_formatter('{x:.0f}') # 格式化 # 数值千分位格式化 from matplotlib.ticker import FuncFormatter ax.yaxis.set_major_formatter( FuncFormatter(lambda v, _: f'{v:,.0f}'))
内置风格主题
# 一行切换全局风格 plt.style.use('ggplot') # 常用: ggplot, seaborn-v0_8, fivethirtyeight, dark_background, # bmh, solarized_light2, tableau-colorblind10 # 临时使用某风格 with plt.style.context('dark_background'): plt.plot(x, y) # 查看所有可用风格 print(plt.style.available) # 恢复默认 plt.rcdefaults()
四、Seaborn:统计可视化
基于 Matplotlib 的高级 API,与 DataFrame 深度集成,一行代码出统计图。
两套 API 的关系
函数级接口:sns.histplot() 等直接画图,简单快速。
对象级接口(新):sns.objects.Plot() 链式语法,更灵活。
通用参数约定
sns.xxxplot(data=df, # DataFrame x='列名', y='列名', hue='分类列', # 颜色分组 size='数值列', # 大小编码 style='分类列', # 标记形状 palette='husl', # 调色板 ax=ax) # 画到指定ax
核心图表速查
import seaborn as sns df = sns.load_dataset('tips') # ── 关系类 ── sns.scatterplot(data=df, x='total_bill', y='tip', hue='day', ax=ax1) sns.lineplot(data=df, x='size', y='tip', errorbar=('ci', 95), ax=ax2) sns.regplot(data=df, x='total_bill', y='tip') # 散点+回归线 # ── 分布类 ── sns.histplot(data=df, x='total_bill', kde=True, hue='sex') # 直方+密度 sns.kdeplot(data=df, x='total_bill', fill=True) # 密度曲线 sns.ecdfplot(data=df, x='total_bill') # 经验累积分布 sns.rugplot(data=df, x='total_bill') # 地毯图 # ── 分类类 ── sns.boxplot(data=df, x='day', y='total_bill', hue='sex') # 箱线 sns.violinplot(data=df, x='day', y='total_bill', split=True) # 小提琴 sns.stripplot(data=df, x='day', y='total_bill', jitter=True) # 散点抖动 sns.swarmplot(data=df, x='day', y='total_bill') # 防重叠散点 sns.barplot(data=df, x='day', y='total_bill', estimator='mean') # 均值柱状+误差条 sns.countplot(data=df, x='day', hue='sex') # 计数柱状 sns.pointplot(data=df, x='day', y='total_bill') # 点图(均值±CI) # ── 矩阵类 ── sns.heatmap(df.corr(numeric_only=True), annot=True, fmt='.2f', cmap='coolwarm', center=0, linewidths=0.5) # 相关性热力图 # ── 回归类 ── sns.lmplot(data=df, x='total_bill', y='tip', hue='smoker', col='time')
FacetGrid 分面(重点)
# 按类别拆成多个子图,同一张图逻辑 g = sns.FacetGrid(df, col='time', row='sex', hue='smoker') g.map_dataframe(sns.scatterplot, x='total_bill', y='tip') g.add_legend() # 便捷版:relplot / displot / catplot sns.relplot(data=df, x='total_bill', y='tip', col='day', col_wrap=2, kind='scatter')
样式与调色板
# 全局主题: darkgrid whitegrid dark # white ticks paper talk sns.set_theme(style='whitegrid', context='notebook', # paper notebook talk poster font='SimHei') # 取消边框 sns.despine(left=True, top=True, right=True) # 调色板 sns.color_palette('Set2') # 分类: Set1/2, tab10, husl sns.color_palette('Blues', 8) # 顺序 sns.color_palette('RdBu_r') # 发散 sns.palplot(sns.color_palette('husl')) # 预览
五、Pandas 可视化
DataFrame 自带 .plot() 方法(底层是 Matplotlib),适合探索性分析快速出图。
import pandas as pd df = pd.DataFrame(np.random.randn(100, 4), columns=list('ABCD')) df.plot(kind='line') # 折线;df.plot.line() 等价 df.plot(kind='bar') # 柱状(多列自动分组) df.plot(kind='barh', stacked=True) # 堆叠条形图 df.plot(kind='hist', bins=30, alpha=0.5) # 多列直方图叠加 df.plot(kind='box') # 箱线图 df.plot(kind='kde') # 核密度估计 df.plot(kind='area') # 面积图 df.plot(kind='scatter', x='A', y='B', c='C', cmap='viridis') df.plot(kind='hexbin', x='A', y='B', gridsize=20) # 六边形密度图 df.plot(kind='pie', subplots=True, autopct='%.0f%%') # 多子图 & 次坐标轴 df.plot(subplots=True, layout=(2,2), figsize=(10,6), sharex=True) df.plot(secondary_y=['D']) # D列用右轴 # 时间序列常用 ts.plot(figsize=(12,4), title='时序') ts.rolling(30).mean().plot() # 30日均线 # 单列/单值快速图 df['A'].value_counts().plot(kind='bar') df.groupby('cat')['v'].sum().plot(kind='pie')
适用场景:Pandas.plot 胜在快,精细控制仍建议拿到
ax 后用 Matplotlib 定制:ax = df.plot(...)六、Plotly:交互式可视化
生成的图表支持缩放、悬停提示、图例点击隐藏,可导出 HTML 网页。是数据大屏和网页报告的首选。
Plotly Express(推荐入门)
import plotly.express as px df = px.data.gapminder() # 折线 px.line(df, x='year', y='lifeExp', color='continent', line_group='country') # 气泡散点(动画!) px.scatter(df, x='gdpPercap', y='lifeExp', size='pop', color='continent', hover_name='country', log_x=True, animation_frame='year') # 柱状 / 饼 / 箱线 / 直方 px.bar(df, x='continent', y='pop', color='continent') px.pie(df, names='continent', values='pop', hole=0.4) px.box(df, x='continent', y='lifeExp', points='all') px.histogram(df, x='lifeExp', nbins=30) # 热力图 / 3D散点 px.imshow(corr_matrix, text_auto=True) px.scatter_3d(df, x='gdpPercap', y='pop', z='lifeExp', color='continent') # 地图 px.choropleth(df, locations='iso_alpha', color='lifeExp', hover_name='country', animation_frame='year')
底层 Graph Objects(精细控制)
import plotly.graph_objects as go fig = go.Figure() fig.add_trace(go.Scatter(x=x, y=y, mode='lines+markers', name='系列A', line=dict(color='royalblue', width=2))) fig.add_trace(go.Bar(x=cx, y=cy, name='系列B', yaxis='y2')) fig.update_layout( title='标题', xaxis_title='X', yaxis_title='Y', template='plotly_dark', # plotly / white / seaborn hovermode='x unified', legend=dict(orientation='h', y=1.05), yaxis2=dict(overlaying='y', side='right')) fig.show() # 保存为 HTML / 图片 fig.write_html('chart.html') fig.write_image('chart.png', scale=2) # 需 kaleido # 在 Jupyter 中显示 fig.show() # 自动渲染交互图
其他值得了解的库
| 库 | 特点 | 适用场景 |
|---|---|---|
pyecharts | 基于 ECharts,中文文档友好,图表华丽 | 中文大屏、网页报表 |
bokeh | 浏览器端渲染,支持 Dash 应用 | 交互式 Web 应用 |
altair | 声明式语法,Vega-Lite 内核 | 快速探索、简洁语法 |
plotnine | ggplot2 语法移植 | 熟悉 R 语言的用户 |
wordcloud | 词云生成 | 文本关键词展示 |
folium / pygmt | 地图可视化 | 地理数据 |
七、图表选型指南
选错图表 = 数据白讲。按下表对号入座。
| 分析目的 | 推荐图表 | 不推荐 |
|---|---|---|
| 看趋势(随时间变化) | 折线图、面积图 | 饼图 ❌ |
| 比较类别大小 | 柱状图、条形图 | 3D柱状 ❌ |
| 看占比构成 | 饼图/环形图(≤5类)、堆叠柱状图 | 类别过多的饼图 ❌ |
| 看相关性 | 散点图、热力图、气泡图 | 折线图(无序数据)❌ |
| 看分布 | 直方图、KDE、箱线图、小提琴图 | 均值柱状图(丢信息)❌ |
| 多变量关系 | 散点矩阵、平行坐标图、气泡图 | — |
| 地理数据 | choropleth 地图、散点地图 | — |
| 流程/层级 | 桑基图、树状图、旭日图 | — |
| 文本数据 | 词云、条形词频图 | — |
可视化设计原则
- 数据墨水比:去掉一切不承载信息的元素(去边框、去网格线、去3D)
- 颜色克制:同一图不超过 6~7 种颜色;用颜色突出重点而非装饰
- 0 基线:柱状图必须从 0 开始,否则视觉夸大差异
- 标注直接:重要数值直接标在图上,少让读者查坐标轴
- 标题讲结论:用"销售额三年增长 40%"而不是"销售额柱状图"
色盲友好配色
# Matplotlib 色盲友好 plt.style.use('tableau-colorblind10') # Seaborn 色盲友好调色板 sns.set_palette('colorblind') # 或 'deep' / 'muted' / colorbrewer 主题 # 经典 Okabe-Ito 色板 okabe_ito = ['#E69F00', '#56B4E9', '#009E73', '#F0E442', '#0072B2', '#D55E00', '#CC79A7']
八、实战技巧与常见坑
⚠️ 常见问题速解
- 中文乱码:设置
font.sans-serif+axes.unicode_minus=False - 图例乱码/缺字:字体不支持该字符,换完整中文字体
- 柱状图 x 轴错位:用
ax.set_xticks(positions, labels)而非传字符串给 bar - 保存后图被裁剪:加
bbox_inches='tight' - 图片模糊:
dpi=300,或保存为 SVG/PDF 矢量格式 - 标签重叠:
plt.tight_layout()或rotation=45 - Jupyter 不显示图:
%matplotlib inline(新版本默认开启) - 内存累积:循环画图时用
plt.close(fig)释放画布
🎨 高级技巧
# 1. 动画(FuncAnimation) from matplotlib.animation import FuncAnimation anim = FuncAnimation(fig, update, frames=100, interval=50) anim.save('a.gif', writer='pillow') # 2. 3D 图 from mpl_toolkits.mplot3d import Axes3D ax = fig.add_subplot(projection='3d') ax.plot_surface(X, Y, Z, cmap='viridis') # 3. 表格+图组合 ax.table(cellText=df.values, colLabels=df.columns, loc='bottom') # 4. 水印背景图 ax.imshow(img, extent=[0,10,0,10], alpha=0.3, aspect='auto')
学习路线建议
| 阶段 | 目标 | 建议 |
|---|---|---|
| 入门 | Matplotlib 基础 + Pandas.plot | 能画出 8 种基本图表,理解 fig/ax |
| 进阶 | Seaborn 统计图表 + 样式定制 | 熟悉 hue/分面/调色板,出图美观 |
| 熟练 | Plotly 交互图 + 子图布局 | 能做动态图表、导出 HTML 报告 |
| 精通 | 面向对象 API 深入 + 自定义 Artist | 阅读官方源码,能复刻商业图表 |
资源:Matplotlib 官方 Gallery(matplotlib.org/stable/gallery)、Seaborn 官方 Tutorial、Plotly 官方 Examples —— 看图反查代码是最高效的学习方式。