Plotly堆叠柱状图实现单柱内从大到小(底部最大)单独排序的方法
Plotly堆叠柱状图实现单柱内从大到小(底部最大)单独排序的方法
我完全懂你的困扰——Plotly Express确实没给px.bar加直接控制单堆排序的参数,用常规的sort_values也没法直接对每行单独排序。不过咱们可以换个思路,从数据预处理阶段入手,把每个资源(Resource)对应的技术(Technology)按数值从大到小排好序,再传给Plotly绘图就行,具体步骤如下:
核心思路
Plotly的堆叠顺序是跟着数据中类别出现的顺序走的,所以我们只需要:
- 把宽格式的聚合数据转成长格式
- 按每个
Resource分组,对组内的Prod_Con_GWh_per_Yr做降序排序 - 用排序后的长格式数据绘图,就能实现每个堆叠单独从大到小排列(大的在底部)
修改后的完整代码
把你原来的代码里的绘图部分替换成下面的逻辑就行,我把完整流程整合好了:
import pandas as pd import plotly.express as px # 你的原始数据处理部分保持不变 df = pd.read_excel(excel_file, sheet_name=0) resources_to_plot = ['Elec (Grid)','Heat (Dom)', 'Heat (Com)','Heat (Ind - LT)', 'Heat (Ind)'] df_filtered = df[(df['Scenario'] == 'Case1c') & (df['Resource'].isin(resources_to_plot)) & (df['Prod_Con_GWh_per_Yr'] > 0)] aggregated_data = df_filtered.groupby(['Resource','Technology'])['Prod_Con_GWh_per_Yr'].sum().unstack() ordered_resources = ['Elec (Grid)', 'Heat (Dom)', 'Heat (Com)', 'Heat (Ind - LT)', 'Heat (Ind)'] aggregated_data = aggregated_data.reindex(ordered_resources) # 新增:数据转长格式并按每个Resource单独降序排序 # 转长格式,把每个Technology的数值拆成单独行 long_format_data = aggregated_data.reset_index().melt( id_vars='Resource', var_name='Technology', value_name='Prod_Con_GWh_per_Yr' ) # 过滤掉可能的0值(可选,因为你之前已经过滤过Prod_Con_GWh_per_Yr > 0) long_format_data = long_format_data[long_format_data['Prod_Con_GWh_per_Yr'] > 0] # 按Resource分组,每组内按数值从大到小排序 sorted_long_data = long_format_data.groupby('Resource', group_keys=False).apply( lambda group: group.sort_values(by='Prod_Con_GWh_per_Yr', ascending=False) ) # 用排序后的长数据绘制堆叠柱状图 fig = px.bar( sorted_long_data, x='Resource', y='Prod_Con_GWh_per_Yr', color='Technology', title='Title', labels={'Prod_Con_GWh_per_Yr': 'Prod_Con_GWh_per_Yr', 'Technology': 'Technology'}, barmode='stack' ) fig.show()
关键说明
- 你之前尝试的
sort_values是针对整个DataFrame的列排序,而我们这里用groupby('Resource').apply(...)是对每个资源对应的技术组单独排序,完美匹配你“每行单独排序”的需求。 - 转长格式后用
color指定Technology类别,比直接传y列列表更灵活,也能让Plotly严格按照我们排序后的顺序来堆叠柱子,确保每个堆叠的底部都是当前资源下数值最大的技术。
备注:内容来源于stack exchange,提问作者Peter James
相关产品推荐
相关产品推荐

