Python实现无需手动拆分数据自动创建条形图子图
按ID自动生成独立条形子图实现方案
不需要手动拆分数据集,借助可视化库的原生分面/分组遍历能力即可自动完成多子图绘制,以下是两种可直接运行的实现方式:
前置数据预处理
首先确保日期字段格式正确,避免x轴时序错乱:
import pandas as pd import seaborn as sns import matplotlib.pyplot as plt # 构造示例数据集,实际使用时替换为你的DataFrame即可 df = pd.DataFrame([ ["2022-05-31",21,1],["2022-05-31",22,4],["2022-05-31",28,3], ["2022-06-01",21,2],["2022-06-01",22,9],["2022-06-01",28,2], ["2022-06-02",22,12],["2022-06-03",22,10],["2022-06-03",23,1], ["2022-07-03",25,1],["2022-07-04",22,12],["2022-07-04",23,6], ["2022-07-04",25,7],["2022-08-05",22,12],["2022-08-05",23,12], ["2022-08-05",25,11],["2022-08-06",22,8],["2022-08-06",23,11], ["2022-08-06",25,11] ], columns=["Date","ID","Data"]) # 转换日期格式 df["Date"] = pd.to_datetime(df["Date"])
方案1:Seaborn分面接口(代码量最少)
Seaborn的catplot函数原生支持按指定字段自动拆分子图,*col="ID"*是实现自动分面的核心参数,不需要手写任何分组、循环逻辑:
sns.catplot( data=df, x="Date", y="Data", col="ID", # 按ID字段拆分独立子图 kind="bar", # 指定绘制条形图 col_wrap=3, # 每行排布3个子图,避免横向过挤 height=3, # 单个子图高度 aspect=1.5 # 单个子图宽高比 ) # 旋转x轴日期标签避免重叠 for ax in plt.gcf().axes: ax.tick_params(axis='x', rotation=45) plt.tight_layout() plt.show()
该方案的特点:
- 自动识别所有唯一ID,自动匹配子图数量,后续数据集ID增减不需要修改代码
- 自动为每个子图添加对应ID作为标题
- 默认统一所有子图的坐标轴尺度,方便跨ID对比
- 不需要手动拆分数据集、创建子图网格
方案2:Matplotlib+GroupBy(自定义程度更高)
如果需要更灵活的样式自定义,可以用pandas自带的groupby自动按ID分组遍历,配合Matplotlib生成子图矩阵,同样不需要手动拆分数据集:
unique_ids = df["ID"].unique() n_id = len(unique_ids) # 自动计算子图行列数,默认每行放3个子图 n_cols = 3 n_rows = (n_id + n_cols - 1) // n_cols # 生成子图矩阵 fig, axes = plt.subplots(n_rows, n_cols, figsize=(15, 8)) axes = axes.flatten() # 将二维子图数组展平为一维方便遍历 # 按ID自动分组循环绘图 for idx, (id_val, group_data) in enumerate(df.groupby("ID")): current_ax = axes[idx] current_ax.bar(group_data["Date"], group_data["Data"]) current_ax.set_title(f"ID: {id_val}") current_ax.tick_params(axis='x', rotation=45) # 关闭ID数量不足时产生的空白子图 for idx in range(n_id, len(axes)): axes[idx].axis('off') plt.tight_layout() plt.show()
两种方案都可以自动适配任意数量的ID分组,不需要针对固定ID数量写硬编码逻辑,替换输入的DataFrame即可直接复用。
内容的提问来源于stack exchange,提问作者thentangler
相关产品推荐
相关产品推荐

