绘制每个 Pandas 组中唯一值数量的条形图

Plot barchart of number of unique values in each Pandas group

我想用 Matplotlib 或 Seaborn 制作一个条形图来表示每个月的唯一值的数量:

import pandas as pd

date_list = ['jan', 'jan', 'jan', 'jan', 'feb', 'feb', 'feb', 'feb', 'mar', 'mar', 'mar', 'mar']
value_list = ['high', 'high', 'high', 'high', 'medium', 'high', 'low', 'low', 'low', 'low', 'low', 'high']

print(len(date_list))
print(len(value_list))

df = pd.DataFrame({'date': date_list,
                  'value': value_list})
                  
print(df)

    date   value
0   jan    high
1   jan    high
2   jan    high
3   jan    high
4   feb  medium
5   feb    high
6   feb     low
7   feb     low
8   mar     low
9   mar     low
10  mar     low
11  mar    high



Unique values:

jan: 1
feb: 3
mar: 2

图表应按月排序。

我知道我能做到:

sns.countplot(x = 'date', hue = 'value', data = df)

但这给了我 value_list

中每个类别的计数

使用DataFrameGroupBy.nunique with Series.plot.bar:

s = df.groupby('date', sort=False)['value'].nunique()

s.plot.bar()

或通过 DataFrame.drop_duplicates 删除两列的重复项并删除 hue 参数:

sns.countplot(x = 'date', data = df.drop_duplicates(['date','value']))

编辑:在同一个 x-axis 中绘制多个 DataFrame 的解决方案:

df2 = pd.DataFrame({'date': date_list[:5],
                  'value': value_list[:5]})
                  
print(df2)

dfs = [df1, df2]

df = (pd.concat(dfs, keys=range(len(dfs))).rename_axis(('no', 'i'))
        .reset_index()
        .drop_duplicates(['no', 'date','value'])_

print (df)
    no   i date   value
0    0   0  jan    high
4    0   4  feb  medium
5    0   5  feb    high
6    0   6  feb     low
8    0   8  mar     low
11   0  11  mar    high
12   1   0  jan    high
16   1   4  feb  medium

# df1.plot.bar(x='date', y='count nunique')
sns.countplot(x = 'date', hue = 'no', data = df)

您需要先自己计算分组。然后喂给 barplot 而不是 countplot:

df2 = (df.groupby('date', sort=False)
         .agg(**{'unique values': ('value', 'nunique')})
         .reset_index()
      )

#   date  unique values
# 0  jan              1
# 1  feb              3
# 2  mar              2


sns.barplot(data=df2, x='date', y='unique values')

输出:

确保月份的顺序(以及所有的存在):

from calendar import month_abbr  # use month_name for full names

# or use a hand defined list
order = [m.lower()for m in month_abbr][1:]
# ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec']

df2 = (df.groupby('date', sort=False)
         .agg(**{'unique values': ('value', 'nunique')})
         .reindex(order)
         .reset_index()
      )
sns.barplot(data=df2, x='date', y='unique values')

输出: