如何在 pandas 中反转堆叠条形图的图例

How to reverse the legends of stacked barplot in pandas

我有一个数据集,其中包含一些按年计算的一些作物产量的记录。因此,我在堆叠条形图中可视化了每年产量最高的作物。我用过的数据集可以在kaggle PMFBY Coverage.csv.

中找到

这是我的代码。

# Top Crop by year
plt.figure(figsize=(12, 6))

df_crg_[df_crg_.year==2018].groupby('cropName').size().nlargest(5).plot(kind='barh', color='red', label='2018')
df_crg_[df_crg_.year==2019].groupby('cropName').size().nlargest(5).plot(kind='barh', color='green', label='2019')
df_crg_[df_crg_.year==2020].groupby('cropName').size().nlargest(5).plot(kind='barh', color='blue', label='2020')
df_crg_[df_crg_.year==2021].groupby('cropName').size().nlargest(5).plot(kind='barh', color='maroon', label='2021')

plt.legend(loc="upper right")
plt.xlabel('Total Production Time')
plt.title('Top Crop by year')
plt.show()

这是输出

现在,如果您查看图表,您会注意到堆叠条形图图例受到尊重,它首先显示 2021 年的状态而不是 2018 年。所以我想颠倒这个表示顺序。

我找到了一个 这个问题,但我不知道如何应用它,因为它是将绘图命令分配给一个变量,但在我的例子中,有四个绘图命令。


只有这个答案可以,但如果知道并且可以回答任何其他按年份提取最高产量作物的方法,那就太好了。如果您在这里注意到,我每年都在手动检查,然后提取当年的最高收成。我试着用 groupby 做,但我无法得到答案。

谢谢

首先,每年需要选择相同的 5 种作物。否则,您无法对 y-axis.

进行固定排序

获得具有 总体 5 most-frequent 作物的地块的最简单方法是 seaborn 的 sns.countplot 并限制为最大的 5 个。请注意,seaborn 强烈反对堆叠条形图,因此您会得到“闪避”条形图(更容易逐年比较,逐年裁剪):

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np

df = pd.read_csv('PMFBY coverage.csv')

sns.set_style('white')
order = df.groupby('cropName').size().sort_values(ascending=False)[:5].index
plt.figure(figsize=(12, 5))
ax = sns.countplot(data=df, y='cropName', order=order, hue='year')
for bars in ax.containers:
    ax.bar_label(bars, fmt='%.0f', label_type='edge', padding=2)
sns.despine()
plt.tight_layout()
plt.show()

使用 pandas,您可以获得堆叠条,但需要更多操作:

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np

df = pd.read_csv('PMFBY coverage.csv')
sns.set_style('white')
order = df.groupby('cropName').size().sort_values(ascending=False)[:5].index
df_5_largest = df[df['cropName'].isin(order)]
df_5_largest_year_count = df_5_largest.groupby(['cropName', 'year']).size().unstack('year').reindex(order)
ax = df_5_largest_year_count.plot.barh(stacked=True, figsize=(12, 5))
ax.invert_yaxis()
for bars in ax.containers:
    ax.bar_label(bars, fmt='%.0f', label_type='center', color='white', fontsize=16)
sns.despine()
plt.tight_layout()
plt.show()

现在,如果您考虑每一年的 5 大作物,请将此与条形图的外观进行比较。请注意每年的作物及其顺序有何不同。您如何将这些信息组合到一个图中?

sns.set_style('white')
fig, axs = plt.subplots(2, 2, figsize=(14, 8))

df[df.year == 2018].groupby('cropName').size().nlargest(5).plot(kind='barh', color='C0', title='2018', ax=axs[0, 0])
df[df.year == 2019].groupby('cropName').size().nlargest(5).plot(kind='barh', color='C1', title='2019', ax=axs[0, 1])
df[df.year == 2020].groupby('cropName').size().nlargest(5).plot(kind='barh', color='C2', title='2020', ax=axs[1, 0])
df[df.year == 2021].groupby('cropName').size().nlargest(5).plot(kind='barh', color='C3', title='2021', ax=axs[1, 1])
for ax in axs.flat:
    ax.bar_label(ax.containers[0], fmt='%.0f', label_type='edge', padding=2)
    ax.margins(x=0.1)
sns.despine()
plt.tight_layout()
plt.show()