【问题标题】:Ordering of elements in Pandas stacked bar chartPandas 堆积条形图中元素的排序
【发布时间】:2020-11-04 20:35:18
【问题描述】:

我正在尝试绘制有关某个地区 5 个地区的特定行业的家庭收入部分的图表信息。

我使用 groupby 按地区对数据框中的信息进行排序:

df = df_orig.groupby('District')['Portion of income'].value_counts(dropna=False)
df = df.groupby('District').transform(lambda x: 100*x/sum(x))
df = df.drop(labels=math.nan, level=1)
ax = df.unstack().plot.bar(stacked=True, rot=0)
ax.set_ylim(ymax=100)

display(df.head())

    District  Portion of income
    A         <25%                 12.121212
              25 - 50%              9.090909
              50 - 75%              7.070707
              75 - 100%             2.020202

由于此收入属于分类,我想以合乎逻辑的方式对堆叠条中的元素进行排序。 Pandas 生成的图表如下。现在,排序(从每个栏的底部开始)是:

  • 25 - 50%
  • 50 - 75%
  • 75 - 100%
  • 不确定

我意识到这些是按字母顺序排序的,我很好奇是否有办法设置自定义排序。为了直观起见,我希望顺序是(同样,从栏的底部开始):

  • 不确定
  • 25 - 50%
  • 50 - 75%
  • 75 - 100%

然后,我想翻转图例以显示此顺序的相反顺序(即,我希望图例顶部有 75 - 100,因为这将是条形顶部的值)。

【问题讨论】:

  • 您能否在code-formatted text 中提供一些起始样本数据? 5-10 行就足够了。

标签: python pandas matplotlib plot


【解决方案1】:

要对收入类别施加自定义排序顺序,一种方法是将它们转换为CategoricalIndex

要反转 matplotlib 图例条目的顺序,请使用此 SO 问题中的 get_legend_handles_labels 方法:Reverse legend order pandas plot

import pandas as pd
import numpy as np
import math

np.random.seed(2019)

# Hard-code the custom ordering of categories
categories = ['unsure', '<25%', '25 - 50%', '50 - 75%', '75 - 100%']

# Generate some example data
# I'm not sure if this matches your input exactly
df_orig = pd.DataFrame({'District': pd.np.random.choice(list('ABCDE'), size=100), 
                        'Portion of income': np.random.choice(categories + [np.nan], size=100)})

# Unchanged from your code. Note that value_counts() returns a 
# Series, but you name it df
df = df_orig.groupby('District')['Portion of income'].value_counts(dropna=False)
df = df.groupby('District').transform(lambda x: 100*x/sum(x))

# In my example data, np.nan was cast to the string 'nan', so 
# I have to drop it like this
df = df.drop(labels='nan', level=1)

# Instead of plotting right away, unstack the MultiIndex
# into columns, then convert those columns to a CategoricalIndex 
# with custom sort order
df = df.unstack()

df.columns = pd.CategoricalIndex(df.columns.values, 
                                 ordered=True, 
                                 categories=categories)

# Sort the columns (axis=1) by the new categorical ordering
df = df.sort_index(axis=1)

# Plot
ax = df.plot.bar(stacked=True, rot=0)
ax.set_ylim(ymax=100)

# Matplotlib idiom to reverse legend entries 
handles, labels = ax.get_legend_handles_labels()
ax.legend(reversed(handles), reversed(labels))

【讨论】:

    猜你喜欢
    • 2018-05-09
    • 1970-01-01
    • 1970-01-01
    • 2014-07-07
    • 1970-01-01
    • 2016-05-24
    相关资源
    最近更新 更多