如何在Pandas DataFrame中同时获取多列的值计数?

113

如果有一个包含多列分类值(0或1)的Pandas DataFrame,是否可以方便地同时获得每列的value_counts?

例如,假设我按照以下方式生成了一个DataFrame:

import numpy as np
import pandas as pd
np.random.seed(0)
df = pd.DataFrame(np.random.randint(0, 2, (10, 4)), columns=list('abcd'))
我可以得到这样的DataFrame:
   a  b  c  d
0  0  1  1  0
1  1  1  1  1
2  1  1  1  0
3  0  1  0  0
4  0  0  0  1
5  0  1  1  0
6  0  1  1  1
7  1  0  1  0
8  1  0  1  1
9  0  1  1  0

如何方便地获取每个列的值计数并方便地获得以下结果?

   a  b  c  d
0  6  3  2  6
1  4  7  8  4

我的当前解决方案是:

pieces = []
for col in df.columns:
    tmp_series = df[col].value_counts()
    tmp_series.name = col
    pieces.append(tmp_series)
df_value_counts = pd.concat(pieces, axis=1)

但是一定有更简单的方法,例如堆叠、透视或分组吗?

15个回答

169

只需调用apply并传递pd.Series.value_counts即可:

In [212]:
df = pd.DataFrame(np.random.randint(0, 2, (10, 4)), columns=list('abcd'))
df.apply(pd.Series.value_counts)
Out[212]:
   a  b  c  d
0  4  6  4  3
1  6  4  6  7

1
如何在此处添加 dropna=False? - branwen85
1
默认情况下,na不会被丢弃。 - Data Mastery
3
同样的问题,您要如何添加“normalize=True”呢?——抱歉,我找到了解决方法:df.apply(pd.Series.value_counts, normalize=True)。 - Charlotte Deng

49

实际上,使用crosstabmelt这两种方法可以更高级、有趣地解决这个问题。

df = pd.DataFrame({'a': ['table', 'chair', 'chair', 'lamp', 'bed'],
                   'b': ['lamp', 'candle', 'chair', 'lamp', 'bed'],
                   'c': ['mirror', 'mirror', 'mirror', 'mirror', 'mirror']})

df

       a       b       c
0  table    lamp  mirror
1  chair  candle  mirror
2  chair   chair  mirror
3   lamp    lamp  mirror
4    bed     bed  mirror

我们可以首先融化DataFrame。

df1 = df.melt(var_name='columns', value_name='index')
df1

   columns   index
0        a   table
1        a   chair
2        a   chair
3        a    lamp
4        a     bed
5        b    lamp
6        b  candle
7        b   chair
8        b    lamp
9        b     bed
10       c  mirror
11       c  mirror
12       c  mirror
13       c  mirror
14       c  mirror

然后使用交叉分析函数对每列的值进行计数。这将保留数据类型为int,而当前选择的答案不会这样做:

pd.crosstab(index=df1['index'], columns=df1['columns'])

columns  a  b  c
index           
bed      1  1  0
candle   0  1  0
chair    2  1  0
lamp     1  2  0
mirror   0  0  5
table    1  0  0

或者在一行中,使用 ** 将列名称扩展为参数名称(这是高级用法)

pd.crosstab(**df.melt(var_name='columns', value_name='index'))

另外,value_counts现在是一个顶级函数。因此,您可以将当前选定的答案简化为以下内容:

df.apply(pd.value_counts)

2
crosstab很好,因为它让你得到整数,虽然我们也可以使用df.apply(pd.value_counts).fillna(0).astype(int)来实现。 - Kevin McDonough

15

只获取特定列的计数:

df[['a', 'b']].apply(pd.Series.value_counts)

这里,df是你的数据框的名称,'a'和'b'是你想要统计值的列。


8
选择所有分类列并一次性生成包含所有值计数的数据框的解决方案:
df = pd.DataFrame({
'fruits': ['apple', 'mango', 'apple', 'mango', 'mango', 'pear', 'mango'],
'vegetables': ['cucumber', 'eggplant', 'tomato', 'tomato', 'tomato', 'tomato', 'pumpkin'],
'sauces': ['chili', 'chili', 'ketchup', 'ketchup', 'chili', '1000 islands', 'chili']})

cat_cols = df.select_dtypes(include=object).columns.tolist()
(pd.DataFrame(
    df[cat_cols]
    .melt(var_name='column', value_name='value')
    .value_counts())
.rename(columns={0: 'counts'})
.sort_values(by=['column', 'counts']))

                            counts
column      value   
fruits      pear            1
            apple           2
            mango           4
sauces      1000 islands    1
            ketchup         2
            chili           4
vegetables  pumpkin         1
            eggplant        1
            cucumber        1
            tomato          4
            

7

您也可以尝试使用以下代码:

for i in heart.columns:
    x = heart[i].value_counts()
    print("Column name is:",i,"and it value is:",x)

4

您的解决方案在一行中的包装看起来甚至比使用groupby、stacking等更简单:

pd.concat([df[column].value_counts() for column in df], axis = 1)

2

使用value_counts函数给出了我意想不到/不太易读的结果。但是这种方法似乎非常简单易懂:

df[["col1", "col2", "col3"]].value_counts()

这是一个如果列具有布尔值的结果示例:
col1               col2         col3
False              False        False        1000
                   True         False        1000
True               False        False        1000
                                True         1000
                   True         False        1000
                                True         1000
dtype: int64

2
你可以使用一个 Lambda 函数:
df.apply(lambda x: x.value_counts())

1
你可以列出列名 list = ["a", "b", "c", "d"] 然后使用value_counts()函数运行for循环
for i in list:
  print(df[i].value_counts())
  print("\n")

你也可以使用下面给出的方法

for column in df.columns:
 print("\n" + column)
 print(df[column].value_counts())

1
这是对我有效的方法:
for column in df.columns:
     print("\n" + column)
     print(df[column].value_counts())

链接到源代码


我会通过选择想要查看的前几个值(例如我的示例中为5),并包括NaN值来增强此答案:df[column].value_counts(dropna= False).nlargest(5) - PeJota

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接