Plotnine:按列分面

Plotnine: facet by column

我的数据框 MedComp 具有以下结构:

我现在想做一个堆叠条形图,每个 Name 一个(有两个不同的),按 Type 堆叠(目前使用颜色完成)。 y 轴是剩余的列,由于范围非常不同,每列都有一个单独的图。对于 Name 中的一种 Crops,我还想显示总数的误差条,目前在一个名为 FarmQuant 的单独数据框中计算,如下所示:

到目前为止,我只使用循环进行管理,因此每列创建一个图形:

Midpoint = [['GHG', 'Total climate change [kg CO2e]'],
            ['Acid', 'Freshwater & ter. acidification [mol H+-Eq]'], 
            ['Terra Eutro', 'Terrestrial eutrophication [mol N-Eq]'], 
            ['Toxicity', 'Freshwater ecotoxicity [CTU]'], 
            ['Marine Eutro', 'Marine eutrophication [kg N-Eq]' ],
           ]

for MPID in range(0, len(Midpoint)):
    print(MPID+1, len(Midpoint), ' ', end='')

    q = (ggplot(Farm_Quant))
         + geom_col(MedComb, aes('Name', Midpoint[MPID][0], fill='Type'))
         + scale_fill_brewer(type='div', palette=2) 
         + geom_point(Farm_Quant, aes(x=1, y=Farm_Quant.loc['q2',Midpoint[MPID][0]]))
         + geom_errorbar(aes(x=1,ymin = Farm_Quant.loc['q1',Midpoint[MPID][0]], ymax = Farm_Quant.loc['q3',Midpoint[MPID][0]]))
         + theme_matplotlib()
         + theme(figure_size=(2.2, 4), legend_position = (1.25, 0.5),
            axis_title_x =element_blank(),
            axis_ticks_major_x=element_blank())
         + scale_y_continuous(name=Midpoint[MPID][1])
         + labs(title = Midpoint[MPID][0]) 
    )

    fig = q.draw()
fig.show()

但是,我想使用 facet 来做到这一点,将所有内容都集中在一个只有一个图例的图形中。有人知道如何使用吗?

请仅提供 matplotlib(据我所知不支持分面)或 plotnine 的示例,因为我已经完成了其他几个绘图,并且希望保持相同的外观。加上我最熟悉的那些。

编辑: 现在这里还有一些测试数据可以使用:

MedComb = pd.DataFrame({
    'Name' : ['Crop1', 'Crop1', 'Crop1', 'Crop1', 'Crop2', 'Crop2', 'Crop2', 'Crop2'],
    'Type' : ['Area', 'Diesel', 'Fert', 'Pest', 'Area', 'Diesel', 'Fert', 'Pest'],
    'GHG':   [14.9, 0.0007, 0.145, 0.1611, 2.537, 0.011, 0.1825, 0.115],
    'Acid':  [0.0125, 0.0005, 0.0029, 0.0044, 0.013, 0.00014, 0.0033, 0.0055],
    'Terra Eutro': [0.053, 0.0002, 0.0077, 0.0001, 0.0547, 0.00019, 0.0058, 0.0002]
})

Farm_Quant = pd.DataFrame({
    'Amount': [0.388, 0.4129, 0.1945],
    'GHG':    [8.029, 20.61, 44.32],
    'Acid':   [0.009, 0.019, 0.044],
    'Terra Eutro': [0.039, 0.077, 0.0177]},
    index = ['q1', 'q2', 'q3']
)

当您的 geom 美学在他们自己的专栏中时,Plotnine 效果最好,因此您可以通过 melt 使用您的数据框来实现分面。此外,如果您将 Farm_Quant 数据框连接到您融化的 MedComb 数据框,那么您可以只引用该单个数据框并删除您的 for 循环。

# Sample Data
MedComb = pd.DataFrame({
    'Name' : ['Crop1', 'Crop1', 'Crop1', 'Crop1', 'Crop2', 'Crop2', 'Crop2', 'Crop2'],
    'Type' : ['Area', 'Diesel', 'Fert', 'Pest', 'Area', 'Diesel', 'Fert', 'Pest'],
    'GHG':   [14.9, 0.0007, 0.145, 0.1611, 2.537, 0.011, 0.1825, 0.115],
    'Acid':  [0.0125, 0.0005, 0.0029, 0.0044, 0.013, 0.00014, 0.0033, 0.0055],
    'Terra Eutro': [0.053, 0.0002, 0.0077, 0.0001, 0.0547, 0.00019, 0.0058, 0.0002]
})

Farm_Quant = pd.DataFrame({
    'Amount': [0.388, 0.4129, 0.1945],
    'GHG':    [8.029, 20.61, 44.32],
    'Acid':   [0.009, 0.019, 0.044],
    'Terra Eutro': [0.039, 0.077, 0.0177]},
    index = ['q1', 'q2', 'q3']
)

# melt the MedComb df from wide to long
med_comb_long = pd.melt(MedComb,id_vars=['Name','Type'],
                        var_name='midpoint',value_name='value')

# Basically transpose the Farm_Quant df in two steps to join with med_comb_long
    # convert the Farm_Quant df from wide to long and make the quarters a column
midpoint_long = pd.melt(Farm_Quant.reset_index().drop(columns=['Amount']),
                        id_vars=['index'],var_name='midpoint',value_name='error_bar')
    # make long farm quant df wide again, but with the quarters as the columns and facet names as index
midpoint_reshape = pd.pivot(midpoint_long,index='midpoint',columns='index',
                            values='error_bar')

# Join the data for the bar charts and error bars/points into single df
plot_data = med_comb_long.join(midpoint_reshape,on='midpoint')

# make the plot
q2 = (ggplot(plot_data)
      + geom_col(aes('Name','value',fill='Type'))
      + scale_fill_brewer(type='div', palette=2)
      + facet_wrap('midpoint',scales='free')
      + geom_errorbar(aes(x=1,ymin='q1',ymax='q3'))
      + geom_point(aes(x=1,y='q2'))
      + theme_matplotlib()
         # + theme(figure_size=(2.2, 4), legend_position = (1.25, 0.5),
         #    axis_title_x =element_blank(),
         #    axis_ticks_major_x=element_blank())
         + scale_y_continuous(name=Midpoint[MPID][1])
         + labs(title = Midpoint[MPID][0]) 
      )
q2