内联图表基础设置
在使用 matplotlib 之前,需要先设置内联显示模式:
# 在 Notebook 顶部执行一次即可 %matplotlib inline import numpy as np import matplotlib.pyplot as plt import pandas as pd # 提高图表分辨率(Retina 屏推荐) %config InlineBackend.figure_format = 'retina' # 设置中文字体(防止乱码) plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS'] plt.rcParams['axes.unicode_minus'] = False
基础折线图
import numpy as np import matplotlib.pyplot as plt x = np.linspace(0, 2 * np.pi, 300) y1 = np.sin(x) y2 = np.cos(x) fig, ax = plt.subplots(figsize=(10, 4)) ax.plot(x, y1, label='sin(x)', color='#f37626', linewidth=2) ax.plot(x, y2, label='cos(x)', color='#4fc3f7', linewidth=2, linestyle='--') ax.set_title('三角函数对比', fontsize=14) ax.set_xlabel('x (弧度)') ax.set_ylabel('y') ax.legend() ax.grid(True, alpha=0.3) plt.tight_layout() plt.show() # 图表直接显示在单元格下方
TIP
使用
fig, ax = plt.subplots() 的面向对象 API,而不是 plt.plot() 过程式 API。在 Notebook 中同时运行多个图表时,面向对象 API 更不容易产生意外的全局状态污染。
子图(Subplots)
fig, axes = plt.subplots(2, 3, figsize=(14, 7)) fig.suptitle('多子图演示', fontsize=16) x = np.linspace(0, 10, 100) # 第一行:折线图、散点图、柱状图 axes[0,0].plot(x, np.sin(x)); axes[0,0].set_title('折线图') axes[0,1].scatter(x, np.random.randn(100)); axes[0,1].set_title('散点图') axes[0,2].bar(['A','B','C','D'], [3,7,2,5]); axes[0,2].set_title('柱状图') # 第二行:直方图、箱线图、饼图 data = np.random.randn(500) axes[1,0].hist(data, bins=30, color='#f37626'); axes[1,0].set_title('直方图') axes[1,1].boxplot([np.random.randn(100) for _ in range(3)]); axes[1,1].set_title('箱线图') axes[1,2].pie([30,25,20,25], labels=['A','B','C','D']); axes[1,2].set_title('饼图') plt.tight_layout() plt.show()
pandas DataFrame 富显示
pandas 的 DataFrame 在 Jupyter 中会自动渲染成格式化的 HTML 表格:
import pandas as pd # DataFrame 直接显示为格式化表格 df = pd.DataFrame({ '语言': ['Python', 'JavaScript', 'Java', 'Go', 'Rust'], '流行度': [85, 78, 65, 55, 48], '薪资指数': [92, 80, 75, 88, 95] }) # 直接输入变量名即可,无需 print df
pandas DataFrame 在 Jupyter 中以 HTML 表格形式渲染,比纯文本更易读
DataFrame 样式设置
# 高亮最大值 df.style.highlight_max(color='#f37626', axis=0) # 数值条形背景 df.style.bar(subset=['流行度', '薪资指数'], color='#4fc3f7') # 设置格式 df.style.format({'流行度': '{:.0f}%', '薪资指数': '{:.0f}K'})
Seaborn 统计图
import seaborn as sns # 使用 Seaborn 内置数据集 tips = sns.load_dataset('tips') fig, axes = plt.subplots(1, 3, figsize=(15, 5)) # 散点图 + 回归线 sns.regplot(data=tips, x='total_bill', y='tip', ax=axes[0]) axes[0].set_title('账单 vs 小费') # 分组箱线图 sns.boxplot(data=tips, x='day', y='total_bill', hue='sex', ax=axes[1]) axes[1].set_title('各天账单分布') # 热力图(相关矩阵) corr = tips[['total_bill', 'tip', 'size']].corr() sns.heatmap(corr, annot=True, cmap='coolwarm', ax=axes[2]) axes[2].set_title('相关矩阵') plt.tight_layout() plt.show()
ipywidgets 交互式控件
ipywidgets 让图表变成可交互的工具:
from ipywidgets import interact, IntSlider import matplotlib.pyplot as plt import numpy as np def plot_sine(frequency=1, amplitude=1): x = np.linspace(0, 2 * np.pi, 300) y = amplitude * np.sin(frequency * x) plt.figure(figsize=(8, 3)) plt.plot(x, y, color='#f37626', linewidth=2) plt.ylim(-3, 3) plt.title(f'sin({frequency}x) × {amplitude}') plt.grid(True, alpha=0.3) plt.show() # 自动生成滑块控件 interact(plot_sine, frequency=IntSlider(min=1, max=10, value=1), amplitude=IntSlider(min=1, max=3, value=1))
INFO
执行上述代码后,Notebook 会在图表下方显示两个滑块。拖动滑块,图表会实时更新——无需重新运行单元格!这是 Jupyter 交互式计算的精髓。
IPython.display 模块
from IPython.display import display, HTML, Image, Audio, Video # 显示 HTML display(HTML('<h3 style="color:#f37626">自定义 HTML</h3>')) # 显示本地图片 display(Image(filename='plot.png', width=400)) # 显示网络图片 display(Image(url='https://example.com/image.png', width=300)) # 在同一单元格显示多个输出 display(df.head()) display(df.describe())
常见图表类型代码模板
import matplotlib.pyplot as plt import numpy as np # ── 热力图(相关矩阵可视化)── import seaborn as sns import pandas as pd data = pd.DataFrame(np.random.randn(100, 4), columns=['A','B','C','D']) corr = data.corr() fig, ax = plt.subplots(figsize=(6, 5)) sns.heatmap(corr, annot=True, # 在格子里显示数值 fmt='.2f', # 数值格式:保留2位小数 cmap='RdYlGn', # 颜色映射:红-黄-绿 vmin=-1, vmax=1, # 数值范围固定 -1 到 1 ax=ax ) ax.set_title('特征相关矩阵') plt.tight_layout() plt.show() # ── 双 Y 轴图(展示不同量级的两组数据)── fig, ax1 = plt.subplots(figsize=(10, 4)) x = np.arange(12) revenue = np.random.randint(100, 500, 12) growth = np.random.uniform(-0.1, 0.3, 12) ax1.bar(x, revenue, color='#4fc3f7', alpha=0.7, label='收入(万元)') ax1.set_ylabel('收入(万元)', color='#4fc3f7') ax2 = ax1.twinx() # 创建共享 X 轴的第二 Y 轴 ax2.plot(x, growth, 'o-', color='#f37626', linewidth=2, label='增长率') ax2.set_ylabel('增长率', color='#f37626') ax2.yaxis.set_major_formatter(plt.FuncFormatter(lambda y, _: f'{y:.0%}')) fig.legend(loc='upper left', bbox_to_anchor=(0.1, 0.9)) plt.title('月度收入与增长率') plt.tight_layout() plt.show()
图表保存与分辨率控制
# 保存高分辨率图表用于发布 fig, ax = plt.subplots(figsize=(8, 5)) ax.plot([1, 2, 3], [4, 1, 3]) # dpi=300 适合印刷,dpi=150 适合网页 fig.savefig('output.png', dpi=150, bbox_inches='tight') fig.savefig('output.pdf', bbox_inches='tight') # PDF 矢量格式 fig.savefig('output.svg') # SVG 矢量,适合网页 # 同时显示并保存(inline 模式下 plt.show() 后 figure 会被清除) # 必须先 savefig 再 show,顺序不能反 fig.savefig('before_show.png') # ✅ 先保存 plt.show() # ✅ 再显示
常见错误:savefig 在 show 之后
在 Jupyter inline 模式下,plt.show() 会清空当前 figure 对象并将其渲染为输出。如果在 plt.show() 之后调用 fig.savefig(),会保存一张空白图片。正确顺序是:先 savefig,再 show。或者保存 fig 对象引用:fig, ax = plt.subplots(),用 fig.savefig() 而不是 plt.savefig(),两者在多图并存时行为不同。
可视化输出的底层原理
%matplotlib inline 的原理
这个魔法命令告诉 matplotlib 使用 inline 后端——将图表渲染为 PNG/SVG 字节流并通过 IPython 的 display 协议嵌入到输出区域,而非弹出独立窗口。这是 Jupyter 图表内联显示的核心机制。%matplotlib widget 则使用 ipympl 后端,支持交互式缩放和平移。
Pandas 的 HTML 富文本渲染
DataFrame 的 __repr__ 方法返回 HTML 字符串(带样式的 HTML 表格),Jupyter 的 display 系统检测到 HTML MIME 类型后,直接将其注入到 Out[n] 区域的 DOM 中。这就是为什么在 Jupyter 中看到的 DataFrame 是美观的表格,而在普通终端看到的是等宽文本。同样原理适用于任何实现了 _repr_html_ 方法的对象。
ipywidgets 的通信机制
ipywidgets 使用 Widget 模型——前端(浏览器 JavaScript)和后端(Kernel Python 对象)通过 WebSocket 同步状态。当用户拖动滑块时,JavaScript 将新值发送给 Kernel;Kernel 更新 Python 对象的 value 属性并触发 observe 回调(或 interact 的目标函数);函数执行后的新图表再通过 display 协议发回浏览器。这个双向通信是实时交互的基础。
本章小结
本章核心要点
- %matplotlib inline:在 Notebook 顶部运行,使图表渲染为内联图像而非弹出窗口;%matplotlib widget 启用交互式图表(需要 ipympl)。每个 Notebook 只需配置一次,通常放在第一个 import 单元格中。
- DataFrame 富文本显示:Pandas DataFrame 在 Jupyter 中自动渲染为 HTML 表格(带样式),是因为实现了 _repr_html_ 方法;用 display(df.style.highlight_max()) 可以添加条件样式,让数据分析报告更直观。
- Seaborn 统计图:基于 matplotlib 的高级封装,一行代码实现分布图(histplot)、关系图(scatterplot)、热力图(heatmap)等;需要在调用前设置 sns.set_theme() 应用主题。适合探索数据关系,不适合精细的生产级图表(用 matplotlib 直接控制细节)。
- ipywidgets 交互式控件:interact() 装饰器最简单,自动从函数参数推断控件类型;复杂交互用 observe() 监听 widget 变化;widgets 需要 ipywidgets 包,且前端需要 JupyterLab 扩展支持才能显示。
- IPython.display 模块:display() 函数可以在一个单元格中产生多个输出;HTML()、Image()、Audio() 分别插入不同媒体类型;这是在报告型 Notebook 中插入图片、HTML 格式化内容的标准方式。