如何用Python的Matplotlib/Seaborn/Plotly实现指定堆叠柱状图?
堆叠分组柱状图实现方案
- 核心实现逻辑:针对每个
weekday(0-6)划分4个time_of_day子分组,每个子分组内部按country堆叠count数值,用Matplotlib手动控制柱状图的位置与堆叠逻辑,避免生成分面图。
代码实现(Matplotlib)
import matplotlib.pyplot as plt import pandas as pd import numpy as np # 假设你的数据集名为df,先预处理数据 # 固定time_of_day的顺序,防止字符串排序打乱分组 time_order = ['first_6hours', 'second_6hours', 'third_6hours', 'last_6hours'] df['time_of_day'] = pd.Categorical(df['time_of_day'], categories=time_order, ordered=True) # 按weekday、time_of_day、country聚合count值(若数据已聚合可跳过此步) agg_df = df.groupby(['weekday', 'time_of_day', 'country'])['count'].sum().unstack(fill_value=0) # 设置绘图参数 bar_width = 0.2 # 单个子分组的宽度 weekdays = agg_df.index.get_level_values('weekday').unique() time_count = len(time_order) # 创建画布 fig, ax = plt.subplots(figsize=(12, 6)) # 遍历每个time_of_day,绘制对应位置的堆叠柱 for idx, time_slot in enumerate(time_order): # 提取当前时间段的所有国家数据 slot_data = agg_df.xs(time_slot, level='time_of_day') # 计算当前分组在X轴上的位置:weekday索引 + 分组偏移量 x_pos = np.arange(len(weekdays)) + idx * bar_width # 初始化堆叠底部位置 bottom = np.zeros(len(weekdays)) # 逐个国家绘制堆叠柱 for country in slot_data.columns: # 仅在第一个时间段添加图例标签,避免重复 ax.bar(x_pos, slot_data[country], width=bar_width, bottom=bottom, label=country if idx == 0 else "") bottom += slot_data[country].values # 配置X轴 ax.set_xlabel('Weekday') ax.set_xticks(np.arange(len(weekdays)) + bar_width * (time_count - 1) / 2) ax.set_xticklabels(weekdays) # 配置Y轴与标题 ax.set_ylabel('Count') ax.set_title('Weekday vs Count (Grouped by Time Slot, Stacked by Country)') # 整理图例,去除重复标签 handles, labels = ax.get_legend_handles_labels() unique_legend = dict(zip(labels, handles)) ax.legend(unique_legend.values(), unique_legend.keys(), title='Country') plt.tight_layout() plt.show()
关键细节说明
- 用
pd.Categorical固定time_of_day的顺序,确保分组严格按需求的4个时间段排列。 - 通过
groupby+unstack将country转为列结构,方便后续堆叠绘制。 - 手动计算每个
time_of_day分组的X轴位置,实现同一weekday下4个分组的并排效果。 - 利用
bottom参数累加前一个国家的count值,实现堆叠效果。 - 图例处理避免重复显示同一国家标签,保持图例简洁。
内容的提问来源于stack exchange,提问作者Sphinx
相关产品推荐
相关产品推荐

