Python 动态交互式数据可视化实战:Matplotlib、Plotly 与 Bokeh 详解
本文详细介绍了 Python 中用于数据可视化的主要库,包括 Matplotlib、Plotly、Bokeh、Seaborn 及 nbinteract。通过 Iris 数据集和特斯拉股票数据的实际案例,演示了如何创建静态图表、3D 动画、交互式时间序列图以及仪表盘组件。内容涵盖从基础绘图到高级交互功能的实现步骤,帮助开发者选择合适的工具进行高效的数据分析与展示。

本文详细介绍了 Python 中用于数据可视化的主要库,包括 Matplotlib、Plotly、Bokeh、Seaborn 及 nbinteract。通过 Iris 数据集和特斯拉股票数据的实际案例,演示了如何创建静态图表、3D 动画、交互式时间序列图以及仪表盘组件。内容涵盖从基础绘图到高级交互功能的实现步骤,帮助开发者选择合适的工具进行高效的数据分析与展示。

在数据分析领域,数据可视化是至关重要的一步。优秀的可视化不仅能帮助开发者更深入地理解数据集中的动态变化,还能让后续的机器学习工作更加高效,同时使他人更容易理解数据背后的逻辑。
本文将详细介绍 Python 中最常用的数据可视化库,包括 Matplotlib、Plotly、Bokeh、Seaborn 以及 nbinteract。通过 Iris 数据集和特斯拉股票数据的实际案例,演示如何创建静态图表、3D 动画、交互式时间序列图以及仪表盘组件。
在开始之前,请确保已安装以下核心库:
pip install matplotlib seaborn plotly bokeh nbinteract imageio ipywidgets pandas numpy scikit-learn
Matplotlib 可能是最广为人知的 Python 数据可视化库。它功能强大,适合生成高质量的静态图像,也支持通过 API 制作简单的动画。
我们可以利用 Matplotlib 结合 Seaborn 加载 Iris 数据集并执行主成分分析(PCA)。成功之后,通过从轴上改变不同角度观察,绘制多张 PCA 方差图,最终合成 GIF。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
import seaborn as sns
import os
from sklearn.decomposition import PCA
import imageio
# 加载数据集
df = sns.load_dataset('iris')
# 设置 DPI
my_dpi = 96
plt.figure(figsize=(480/my_dpi, 480/my_dpi), dpi=my_dpi)
# 处理物种列,使其可用于着色
df['species'] = pd.Categorical(df['species'])
my_color = df['species'].cat.codes
df_processed = df.drop('species', axis=1)
# 执行 PCA
pca = PCA(n_components=3)
pca.fit(df_processed)
# 存储结果
result = pd.DataFrame(pca.transform(df_processed),
columns=['PC1', 'PC2', 'PC3'],
index=df_processed.index)
# 生成不同角度的散点图
for angle in range(70, 210, 2):
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(result['PC1'], result['PC2'], result['PC3'],
c=my_color, cmap="Set2_r", s=60)
# 绘制坐标轴
xAxisLine = ((min(result['PC1']), max(result['PC1'])), (0, 0), (0, 0))
ax.plot(xAxisLine[0], xAxisLine[1], xAxisLine[2], 'r')
yAxisLine = ((0, 0), (min(result['PC2']), max(result['PC2'])), (0, 0))
ax.plot(yAxisLine[0], yAxisLine[1], yAxisLine[2], 'r')
zAxisLine = ((0, 0), (0, 0), (min(result['PC3']), max(result['PC3'])))
ax.plot(zAxisLine[0], zAxisLine[1], zAxisLine[2], 'r')
ax.view_init(30, angle)
ax.set_xlabel("PC1")
ax.set_ylabel("PC2")
ax.set_zlabel("PC3")
ax.set_title("PCA Iris Dataset")
filename = f'./PCA/PCA_angle{angle}.png'
plt.savefig(filename, dpi=96)
plt.close(fig) # 关闭图形以释放内存
# 生成 GIF 函数
def make_gif(input_folder, save_filepath):
episode_frames = []
time_per_step = 0.25
for root, _, files in os.walk(input_folder):
file_paths = [os.path.join(root, file) for file in files]
# 按修改时间排序
file_paths = sorted(file_paths, key=lambda x: os.path.getmtime(x))
episode_frames = [
imageio.imread(file_path)
for file_path in file_paths if file_path.endswith('.png')
]
episode_frames = np.array(episode_frames)
imageio.mimsave(save_filepath, episode_frames, duration=time_per_step)
make_gif('./PCA/', './PCA/PCA.gif')
这种机制可应用于其他场景,如动画分布、轮廓分析和机器学习模型训练过程的可视化。
Celluloid 库可以简化 Matplotlib 中的动画制作。通过创建一个摄像头,每次图形参数变化时拍摄快照,组合成动画。
from celluloid import Camera
import numpy as np
import matplotlib.pyplot as plt
fig, axes = plt.subplots(2)
camera = Camera(fig)
t = np.linspace(0, 5 * np.pi, 128, endpoint=False)
t2 = np.linspace(0, 1 * np.pi, 128, endpoint=False)
for i in t2:
axes[0].plot(t, np.cos(t/2 + i), color='b')
axes[1].plot(t2, np.sin(t2 - i), color='b')
camera.snap()
animation = camera.animate()
animation.save('celluloid_example.gif', writer='imagemagick')
Plotly 是一个基于 plotly.js 的开源 Python 库。它支持在线和离线模式,生成的图表具有高度的交互性,适合在 Web 环境中展示。
使用 Plotly 可以生成交互式的时间序列表。将光标移动到时间轴的任意一点,即可查看高价和低价,并可通过按钮和滑块调整关注的时间范围。
import plotly.graph_objs as go
from plotly.offline import init_notebook_mode, iplot
import pandas as pd
import datetime
init_notebook_mode(connected=True)
# 读取并预处理数据
df = pd.read_csv("TSLA.csv")
df['date'] = df['date'].astype('str')
df['high'] = df['high'].astype('float64')
df['low'] = df['low'].astype('float64')
# 日期格式转换
date2 = []
for i in df['date']:
new_date = datetime.datetime.strptime(i, "%d/%m/%Y").strftime("%Y-%m-%d")
date2.append(new_date)
df['date'] = date2
df.fillna(0)
# 定义轨迹
trace_high = go.Scatter(
x=df.date,
y=df['high'],
name="TSLA High",
line=dict(color='#17BECF'),
opacity=0.8
)
trace_low = go.Scatter(
x=df.date,
y=df['low'],
name="TSLA Low",
line=dict(color='#7F7F7F'),
opacity=0.8
)
data = [trace_high, trace_low]
# 布局配置
layout = dict(
xaxis=dict(
rangeselector=dict(
buttons=list([
dict(count=1, label='1m', step='month', stepmode='backward'),
dict(count=6, label='6m', step='month', stepmode='backward'),
dict(step='all')
])
),
rangeslider=dict(visible=True),
type='date'
)
)
fig = dict(data=data, layout=layout)
iplot(fig, filename="Time Series with Rangeslider")
plotly.offline.plot(fig, filename='Plotly_Stock.html')
Bokeh 库同时支持 Python 和 JavaScript。它的许多图形、交互和小部件都可以用 Python 实现,但在某些情况下需要用到 JavaScript。
我们可以使用 Bokeh 创建四个不同的时间序列(高/低/开盘价和收盘价),并添加复选框。使用者可以通过选中或取消复选框来控制哪些线条显示在图中。
import pandas as pd
import numpy as np
from bokeh.plotting import figure
from bokeh.io import output_file, show, output_notebook
from bokeh.models import CustomJS
from bokeh.models.widgets import CheckboxGroup
from bokeh.layouts import row
from bokeh.palettes import Viridis4
from bokeh.models.annotations import Title, Legend
output_notebook()
# 读取数据
df = pd.read_csv("TSLA.csv")
df['date'] = pd.to_datetime(df['date'], format='%d/%m/%Y')
p = figure(x_axis_type='datetime', plot_width=800)
aline = p.line(df['date'], df['high'], line_width=2, color=Viridis4[0])
bline = p.line(df['date'], df['low'], line_width=2, color=Viridis4[1])
cline = p.line(df['date'], df['open'], line_width=2, color=Viridis4[2])
dline = p.line(df['date'], df['close'], line_width=2, color=Viridis4[3])
p.yaxis.axis_label = 'Price'
p.xaxis.axis_label = 'Time Span'
legend = Legend(items=[
("High Price", [aline]),
("Low Price", [bline]),
("Open Price", [cline]),
("Close Price", [dline])
], location=(0, 450))
t = Title()
t.text = 'Tesla Stock Market Analysis'
p.title = t
p.add_layout(legend, 'left')
checkboxes = CheckboxGroup(labels=list(['High Price', 'Low Price', 'Open Price', 'Close Price']), active=[0, 1, 2, 3])
callback = CustomJS(code="""
aline.visible = false;
bline.visible = false;
cline.visible = false;
dline.visible = false;
// cb_obj is injected in thanks to the callback
if (cb_obj.active.includes(0)){aline.visible = true;}
if (cb_obj.active.includes(1)){bline.visible = true;}
if (cb_obj.active.includes(2)){cline.visible = true;}
if (cb_obj.active.includes(3)){dline.visible = true;}""",
args={'aline': aline, 'bline': bline, 'cline': cline, 'dline': dline})
checkboxes.js_on_click(callback)
output_file('Tesla_Stock_Widget.html')
show(row(p, checkboxes))
此图可另存为 HTML 文件,方便分享和部署。
Seaborn 建立在 Matplotlib 之上,专注于统计图表。如果 Matplotlib 尝试让简单的事情变简单,那么 Seaborn 则致力于让复杂的事情也变得简单。
import seaborn as sns
sns.set(style="ticks")
df = sns.load_dataset("iris")
sns.pairplot(df, hue="species")
Pair Plot 用于展现数据集中一对对变量的图形化摘要,对角线为单变量分布,其余为散点图矩阵。
nbinteract 允许我们在 Jupyter Notebook 上创建交互式小部件,并可导出为 HTML。
from ipywidgets import interact
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
import nbinteract as nbi
def cars(name, number):
return '{} has {} cars!'.format(name, number)
interact(cars, name='Nemo', number={'Zero': 0, 'Two': 2, 'Three': 3, 'Ten': 10});
除了上述库外,Pygal 和 Altair 也是常用的 Python 库。它们提供了类似的图表功能,但更适合创建金字塔图、树状图、地图和甘特图等特定类型的图形。
| 库名 | 特点 | 适用场景 |
|---|---|---|
| Matplotlib | 基础、灵活、静态为主 | 学术论文、静态报告、自定义绘图 |
| Plotly | 交互性强、Web 友好 | 网页展示、交互式报表、金融数据 |
| Bokeh | 仪表板、组件丰富 | 实时数据监控、Web 应用后台 |
| Seaborn | 统计美观、基于 Matplotlib | 统计分析、探索性数据分析 (EDA) |
| nbinteract | Notebook 原生 | 教学演示、快速原型验证 |
选择合适的可视化工具取决于具体需求。对于静态报告,Matplotlib 和 Seaborn 是首选;若需 Web 端交互,Plotly 和 Bokeh 更为合适。掌握这些工具的组合使用,将极大提升数据分析和展示的效率。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online