pandas 具有两个组的框架的棒棒糖图

y0u0uwnf  于 2023-10-14  发布在  其他
关注(0)|答案(1)|浏览(84)

我有以下dataframe:

Country variable      value
0                 Afghanistan     Area  38.232510
1                 Afghanistan     Yield  70.081666
2                   Argentina     Area  96.776730
3                   Argentina     Area  60.047651
4                   Argentina     Yield  66.811117
..                        ...      ...        ...
133  United States Of America    Yield  53.536069
134  United States Of America    Area   76.975885
135  United States Of America    Yield  19.987656
136                    Zambia    Yield  39.493612
137                    Zambia    Yield  35.384809

我想用它来构造一个棒棒糖图形(例如,https://python-graph-gallery.com/184-lollipop-plot-with-2-groups/)。然而,这个例子的框架与我的不同之处在于,它为每个组提供了两个值,而我想为每个国家的两个组绘制最小值和最大值,其中组由色调区分。我如何通过修改该示例中的代码来做到这一点?

pes8fvy9

pes8fvy91#

这应该是一个很好的起点,可以从中提炼:

df_agg = df.groupby(['Country', 'variable']).agg([min, max]).droplevel(level=0, axis=1).reset_index()

colours = { 
    'Area' : { 'line' : 'pink', 'min' : 'crimson', 'max' : 'red' }, 
    'Yield' : { 'line' : 'skyblue', 'min' : 'navy', 'max' : 'blue' }, 
}

vars = df_agg['variable'].unique()

for var in vars:
    df_plt = df_agg[df_agg['variable'] == var]
    
    my_range = list(df_plt.index)
    
    plt.hlines(y=my_range, xmin=df_plt['min'], xmax=df_plt['max'], color=colours[var]['line'], alpha=0.4)
    plt.scatter(df_plt['min'], my_range, color=colours[var]['min'], alpha=1, label=f'{var} min')
    plt.scatter(df_plt['max'], my_range, color=colours[var]['max'], alpha=1, label=f'{var} max')

# Add legend, title and axis names
plt.legend()
plt.yticks(df_agg.index, df_agg['Country'])
plt.title("Min and Max per Country", loc='left')
plt.xlabel('Values')
plt.ylabel('Country')

# Show the graph
plt.show()

对于您问题中的数据,这给出了:

您还可以通过使my_range值围绕基于Country的整数值浮动,然后仅在这些整数值处放置y刻度来对国家/地区值进行“分组”:

df_agg = df.groupby(['Country', 'variable']).agg([min, max]).droplevel(level=0, axis=1).reset_index()

colours = { 
    'Area' : { 'line' : 'pink', 'min' : 'crimson', 'max' : 'red' }, 
    'Yield' : { 'line' : 'skyblue', 'min' : 'navy', 'max' : 'blue' }, 
}

countries = list(df_agg['Country'].unique())

vars = df_agg['variable'].unique()

# figure out y positions for each lollipop
# make them go from y-0.2 to y+0.2
plot_y = { var : pt for var, pt in zip(vars, np.linspace(-0.2, 0.2, num=len(vars))) }
    
for var in vars:
    df_plt = df_agg[df_agg['variable'] == var]
    
    my_range = list(df_plt['Country'].apply(countries.index) + plot_y[var])
    
    plt.hlines(y=my_range, xmin=df_plt['min'], xmax=df_plt['max'], color=colours[var]['line'], alpha=0.4)
    plt.scatter(df_plt['min'], my_range, color=colours[var]['min'], alpha=1, label=f'{var} min')
    plt.scatter(df_plt['max'], my_range, color=colours[var]['max'], alpha=1, label=f'{var} max')

# Add legend, title and axis names
plt.legend()
plt.yticks(range(len(countries)), countries)
plt.title("Min and Max per Country", loc='left')
plt.xlabel('Values')
plt.ylabel('Country')

# Show the graph
plt.show()

相关问题