【问题标题】:How to get value counts for multiple columns at once in Pandas DataFrame?如何在 Pandas DataFrame 中一次获取多列的值计数?
【发布时间】:2015-12-11 22:22:16
【问题描述】:

给定一个 Pandas DataFrame,它具有多个具有分类值(0 或 1)的列,是否可以方便地同时获取每列的 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)

但一定有更简单的方法,比如堆叠、旋转或分组?

【问题讨论】:

    标签: python numpy pandas


    【解决方案1】:

    用一行包裹的解决方案看起来比使用 groupby、堆叠等更简单:

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

    【讨论】:

      【解决方案2】:

      您可以使用 lambda 函数:

      df.apply(lambda x: x.value_counts())
      

      【讨论】:

        【解决方案3】:

        可以做的另一种解决方案:

        df = pd.DataFrame(np.random.randint(0, 2, (10, 4)), columns=list('abcd'))
        l1 = pd.Series()
        for var in df.columns:
            l2 = df[var].value_counts()
            l1 = pd.concat([l1, l2], axis = 1)
        l1
        

        【讨论】:

          【解决方案4】:

          你也可以试试这个代码:

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

          【讨论】:

            【解决方案5】:

            选择所有分类列并一次创建一个包含所有值计数的数据框的解决方案:

            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
                        
            

            【讨论】:

              【解决方案6】:

              仅获取特定列的计数:

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

              其中 df 是您的数据框的名称,“a”和“b”是您要计算其值的列。

              【讨论】:

                【解决方案7】:

                这对我有用:

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

                link to source

                【讨论】:

                  【解决方案8】:

                  跑到这里看看是否有更好的方法来做我正在做的事情。事实证明,在 DataFrame 上调用 df.apply(pd.value_counts),每列都有自己的许多不同的值,这将导致相当大的性能损失。

                  在这种情况下,最好简单地遍历字典推导中的非数字列,并将其保留为字典:

                  types_to_count = {"object", "category", "string"}
                  result = {
                      col: df[col].value_counts()
                      for col in df.columns[df.dtypes.isin(types_to_count)]
                  }
                  

                  types_to_count 的过滤有助于确保您不会尝试获取连续数据的value_counts

                  【讨论】:

                    【解决方案9】:

                    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
                    

                    然后使用交叉表函数计算每一列的值。这会将数据类型保留为整数,而当前选择的答案不会是这种情况:

                    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)
                    

                    【讨论】:

                    • crosstab 很好,因为它给你留下了整数,虽然我们也可以用df.apply(pd.value_counts).fillna(0).astype(int)
                    【解决方案10】:

                    只需调用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
                    

                    【讨论】:

                    • 如何将 dropna=False 添加到此?
                    • na 默认不会被丢弃
                    • 同样的问题,如何添加“normalize=True”? --- 抱歉找到了解决方案:df.apply(pd.Series.value_counts, normalize=True)
                    猜你喜欢
                    • 2021-01-16
                    • 1970-01-01
                    • 2022-01-19
                    • 1970-01-01
                    • 2013-11-20
                    • 1970-01-01
                    • 1970-01-01
                    • 2013-07-14
                    相关资源
                    最近更新 更多