如何将groupby()和value_count()转换为多个饼图/条形图

问题描述

假设我有一个数据帧,并且我正在查看其中的2列(2个系列)。

使用下面的其中一列--"no_employees"--有人能帮我弄清楚如何创建6个不同的饼图或条形图(每个NO_Employees组1个)来说明处理列中的Yes/No值的值计数吗?我将使用matplotlibseaborn,只要您觉得最简单。

我使用附加的代码行生成下面的代码。

dataframe_title.groupby(['no_employees']).treatment.value_counts(). 

但现在我被卡住了。我要使用seaborn吗?.plot?这看起来应该很简单,我知道在某些情况下我可以做出subplots=True,但是我真的很困惑。非常感谢。

no_employees    treatment
1-5             Yes           88
                No            71
100-500         Yes           95
                No            80
26-100          Yes          149
                No           139
500-1000        No            33
                Yes           27
6-25            No           162
                Yes          127
More than 1000  Yes          146
                No           135

解决方案

数据编码的重要性:
  1. 数据可视化的目的是为了更容易地传达信息(例如,在本例中是每个类别的'treatments'的相对数量)
  2. 条形图便于显示重要信息
    • 每组有多少人说'Yes''No'
    • 每个组的相对大小
  3. 饼图更常用于显示样本,其中样本中的组总和为100%。
    • Wikipedia: Pie Chart
      • 研究表明,按角度比较不如按长度比较准确,因为人们辨别差异的能力较差。
      • Statisticians一般认为饼图是一种很差的信息显示方式,在科学文献中并不常见。
    • 此数据不能用饼图很好地表示,因为每个公司规模都是单独的总体,这将需要正确表示6个饼图。
    • 可以将数据放入饼图(如其他人所示),但这并不意味着应该将其放入饼图中。
  • 无论绘图类型如何,数据的形状对于绘图API都必须正确。
  • 使用pandas 1.3.0seaborn 0.11.1matplotlib 3.4.2
  • 测试

设置测试数据帧

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np  # for sample data only

np.random.seed(365)
cats = ['1-5', '6-25', '26-100', '100-500', '500-1000', '>1000']

data = {'no_employees': np.random.choice(cats, size=(1000,)),
        'treatment': np.random.choice(['Yes', 'No'], size=(1000,))}

df = pd.DataFrame(data)

# set a categorical order for the x-axis to be ordered
df.no_employees = pd.Categorical(df.no_employees, categories=cats, ordered=True)

  no_employees treatment
0       26-100        No
1          1-5       Yes
2        >1000        No
3      100-500       Yes
4     500-1000       Yes

pandas.DataFrame.plot()的id="plotting-with-pandas.dataframe.plot-l84f">Plotting:
  • 这需要将数据帧分组以获取.value_counts,并使用pandas.DataFrame.unstack进行出栈。
# to get the dataframe in the correct shape, unstack the groupby result
dfu = df.groupby(['no_employees']).treatment.value_counts().unstack()

treatment     No  Yes
no_employees         
1-5           78   72
6-25          83   86
26-100        83   76
100-500       91   84
500-1000      78   83
>1000         95   91

# plot
ax = dfu.plot(kind='bar', figsize=(7, 5), xlabel='Number of Employees in Company', ylabel='Count', rot=0)
ax.legend(title='treatment', bbox_to_anchor=(1, 1), loc='upper left')


使用seaborn

打印
  • seaborn是matplotlib的高级接口
seaborn.barplot()
  • 需要整洁(长)格式的DataFrame,方法是将DataFrame分组以获取.value_counts,然后使用pandas.Series.reset_index
  • 重置索引
  • 也可以使用sns.catplot()kind='bar'进行图形级界面操作
# groupby, get value_counts, and reset the index
dft = df.groupby(['no_employees']).treatment.value_counts().reset_index(name='Count')

   no_employees treatment  Count
0           1-5        No     78
1           1-5       Yes     72
2          6-25       Yes     86
3          6-25        No     83
4        26-100        No     83
5        26-100       Yes     76
6       100-500        No     91
7       100-500       Yes     84
8      500-1000       Yes     83
9      500-1000        No     78
10        >1000        No     95
11        >1000       Yes     91

# plot
p = sns.barplot(x='no_employees', y='Count', data=dft, hue='treatment')
p.legend(title='treatment', bbox_to_anchor=(1, 1), loc='upper left')
p.set(xlabel='Number of Employees in Company')
seaborn.countplot()
  • 使用原始数据帧df,不进行任何转换。
  • 也可以使用sns.catplot()kind='count'进行图形级界面操作
p = sns.countplot(data=df, x='no_employees', hue='treatment')
p.legend(title='treatment', bbox_to_anchor=(1, 1), loc='upper left')
p.set(xlabel='Number of Employees in Company')
  • barplotcountplot的输出

相关文章