You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为含288条观测值的用户DataFrame绘制多时间序列子图?

嘿,这个需求我经常碰到!每个用户288条观测(大概率是一天按5分钟采样一次对吧?),要画多子图时间序列的话,有几个非常实用的方法,我给你详细讲讲:

方法一:用Matplotlib手动创建子图

这种方法适合你需要完全控制子图布局的场景,比如自定义每个子图的大小、颜色、刻度细节。

先给你整个模拟数据,方便你直接跑代码测试:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 模拟数据:5个用户,每个288条5分钟间隔的观测
np.random.seed(42)
users = [f'user_{i}' for i in range(5)]
timestamps = pd.date_range(start='2024-01-01', periods=288, freq='5min')
data = []
for user in users:
    # 模拟带趋势的时间序列
    values = np.random.randn(288).cumsum()
    data.extend([(user, ts, val) for ts, val in zip(timestamps, values)])
df = pd.DataFrame(data, columns=['user_id', 'timestamp', 'value'])

然后是绘制多子图的代码:

# 获取所有唯一用户ID
unique_users = df['user_id'].unique()
n_users = len(unique_users)

# 计算子图的行列数(比如每行放3个,行数向上取整)
n_cols = 3
n_rows = (n_users + n_cols - 1) // n_cols

# 创建画布和子图,设置整体大小
fig, axes = plt.subplots(n_rows, n_cols, figsize=(15, n_rows*4))
# 把二维的子图数组转成一维,方便循环遍历
axes = axes.flatten()

# 循环每个用户绘制时间序列
for i, user in enumerate(unique_users):
    user_data = df[df['user_id'] == user]
    axes[i].plot(user_data['timestamp'], user_data['value'], linewidth=1.5)
    axes[i].set_title(f'Time Series: {user}', fontsize=10)
    # 旋转x轴标签避免重叠
    axes[i].tick_params(axis='x', rotation=45, labelsize=8)
    axes[i].set_xlabel('Timestamp', fontsize=8)
    axes[i].set_ylabel('Value', fontsize=8)

# 如果用户数不是行列数的整数倍,隐藏多余的空图
for j in range(i+1, n_rows*n_cols):
    axes[j].axis('off')

# 自动调整子图间距,避免标题和标签重叠
plt.tight_layout()
plt.show()
方法二:用Seaborn的FacetGrid自动生成子图

Seaborn的FacetGrid是处理这种分面绘图的神器,代码更简洁,自动帮你搞定布局,适合快速出图。

import seaborn as sns

# 设置全局绘图风格
sns.set_style('whitegrid')

# 创建分面网格,按user_id拆分,每行最多3个子图
g = sns.FacetGrid(df, col='user_id', col_wrap=3, height=4, aspect=1.2)
# 映射折线图到每个子图
g.map(sns.lineplot, 'timestamp', 'value', linewidth=1.5)

# 设置子图标题和轴标签
g.set_titles('{col_name}', fontsize=10)
g.set_xlabels('Timestamp', fontsize=8)
g.set_ylabels('Value', fontsize=8)

# 旋转x轴标签,避免拥挤
for ax in g.axes.flat:
    ax.tick_params(axis='x', rotation=45, labelsize=8)

plt.tight_layout()
plt.show()
方法三:用Plotly做交互式子图(适合需要交互的场景)

如果想要交互式的图表——比如缩放查看细节、悬停查看具体数值,Plotly是个绝佳选择:

import plotly.subplots as sp
import plotly.graph_objects as go

n_cols = 3
n_rows = (n_users + n_cols - 1) // n_cols

# 创建子图布局,设置每个子图的标题
fig = sp.make_subplots(rows=n_rows, cols=n_cols, subplot_titles=unique_users)

# 循环添加每个用户的时间序列轨迹
for i, user in enumerate(unique_users):
    row = (i // n_cols) + 1
    col = (i % n_cols) + 1
    user_data = df[df['user_id'] == user]
    fig.add_trace(
        go.Scatter(x=user_data['timestamp'], y=user_data['value'], name=user),
        row=row, col=col
    )

# 调整整体布局大小和标题
fig.update_layout(height=n_rows*400, width=1500, title_text="User Time Series Dashboard")
# 旋转x轴标签,优化显示
fig.update_xaxes(tickangle=45)

# 生成交互式图表
fig.show()

几个小提示

  • 如果用户数量特别多(比如几十上百个),别硬画所有子图——太挤根本看不清。可以抽样几个典型用户,或者按用户行为分组绘图,甚至换用热力图这类的可视化方式会更合适。
  • 288条观测是天级的5分钟数据,你可以把x轴刻度改成小时格式,让图表更直观,比如在Matplotlib里加plt.gcf().autofmt_xdate()自动优化日期显示。

内容的提问来源于stack exchange,提问作者Zalan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:13:36