plotnine绘制比例柱状图时fill填充参数失效该如何解决
问题原因
fill失效的核心是group=1参数的优先级高于aes中fill的分组规则:
- 当
geom_bar中设置group=1时,plotnine会强制将所有数据归入同一个全局分组计算占比,fill指定的Flag_Churned分组逻辑被覆盖,因此填充色不生效 - 当移除
group=1时,plotnine默认按x轴的Flag_Churned字段分组计算占比,每个分类的占比都会被计算为100%,不符合「每个分面内的用户流失/留存占比」的需求
解决方法
方法1:调整group参数适配分面计算逻辑
仅需把group=1改成group='Flag_Treat'即可,这样比例计算的分母是每个Flag_Treat分面的总样本数,同时不会覆盖fill的分组规则,填充色可正常生效。修改后的代码如下:
from plotnine import ggplot, aes, geom_bar, theme, facet_wrap, scale_fill_manual, scale_y_continuous, percent_format import pandas as pd def plot_churn(df_): color_dict = { 'Stayed': 'green', 'Churned': 'red' } myplot = ggplot(data=df_, mapping=aes(x='Flag_Churned', fill='Flag_Churned')) # group指定为分面字段,按分面总样本计算占比,同时保留fill分组 myplot += geom_bar(mapping=aes(y="stat(prop)", group='Flag_Treat')) myplot += theme(subplots_adjust={'right': 0.71}) myplot += facet_wrap('Flag_Treat') myplot += scale_fill_manual(values=color_dict) myplot += scale_y_continuous(labels=percent_format()) print(myplot) # 测试代码 data = {'Churn': [0,0,0,1,1,0,1,1], 'Flag_Treat': ['treated','treated','treated','treated','not treated','not treated','not treated','not treated'], 'Flag_Churned': ['Stayed', 'Stayed', 'Stayed', 'Churned', 'Churned', 'Stayed', 'Churned', 'Churned']} df = pd.DataFrame(data=data) plot_churn(df)
方法2:提前用pandas计算占比再绘图(适配复杂场景更稳妥)
如果后续数据逻辑复杂度提升,建议提前预计算好每个分面下的分类占比,直接传入数值绘图,避免stat计算的逻辑偏差:
def plot_churn(df_): color_dict = { 'Stayed': 'green', 'Churned': 'red' } # 预计算每个分面下的分类占比 df_stat = df_.groupby(['Flag_Treat', 'Flag_Churned']).size().reset_index(name='count') df_stat['prop'] = df_stat.groupby('Flag_Treat')['count'].transform(lambda x: x/x.sum()) myplot = ggplot(data=df_stat, mapping=aes(x='Flag_Churned', y='prop', fill='Flag_Churned')) # 直接用geom_col传入预计算好的数值,不需要stat二次计算 myplot += geom_col() myplot += theme(subplots_adjust={'right': 0.71}) myplot += facet_wrap('Flag_Treat') myplot += scale_fill_manual(values=color_dict) myplot += scale_y_continuous(labels=percent_format()) print(myplot)
内容的提问来源于stack exchange,提问作者Jannik
相关产品推荐
相关产品推荐

