【问题标题】:Pandas dataframe: how to apply describe() to each group and add to new columns?Pandas 数据框:如何将 describe() 应用于每个组并添加到新列?
【发布时间】:2016-02-08 02:51:42
【问题描述】:

df:

name score
A      1
A      2
A      3
A      4
A      5
B      2
B      4
B      6 
B      8

想得到如下形式的新数据框:

   name count mean std min 25% 50% 75% max
    A     5    3    .. ..  ..  ..  ..  ..
    B     4    5    .. ..  ..  ..  ..  ..

如何从 df.describe() 中提取信息并重新格式化? 谢谢

【问题讨论】:

    标签: python numpy pandas dataframe


    【解决方案1】:

    还有一个更短的:)

    print df.groupby('name').describe().unstack(1)
    

    没有什么比单线更好的了:

    在 [145] 中:

    打印 df.groupby('name').describe().reset_index().pivot(index='name', values='score', columns='level_1')

    【讨论】:

    • print df.groupby('name').describe().unstack(1).reset_index() 有用
    • df.groupby('name').describe().unstack(1).reset_index().pivot(index='name', values=0, columns='level_1') 会给你一个更好的视野。
    【解决方案2】:

    定义一些数据

    In[1]:
    import pandas as pd
    import io
    
    data = """
    name score
    A      1
    A      2
    A      3
    A      4
    A      5
    B      2
    B      4
    B      6
    B      8
        """
    
    df = pd.read_csv(io.StringIO(data), delimiter='\s+')
    print(df)
    

    .

    Out[1]:
      name  score
    0    A      1
    1    A      2
    2    A      3
    3    A      4
    4    A      5
    5    B      2
    6    B      4
    7    B      6
    8    B      8
    

    解决方案

    解决这个问题的一个很好的方法是使用生成器表达式(见脚注)来允许pd.DataFrame() 迭代groupby 的结果,并动态构建汇总统计数据框:

    In[2]:
    df2 = pd.DataFrame(group.describe().rename(columns={'score':name}).squeeze()
                             for name, group in df.groupby('name'))
    
    print(df2)
    

    .

    Out[2]:
       count  mean       std  min  25%  50%  75%  max
    A      5     3  1.581139    1  2.0    3  4.0    5
    B      4     5  2.581989    2  3.5    5  6.5    8
    

    这里squeeze 函数正在挤出一个维度,将单列组摘要统计Dataframe 转换为Series

    脚注:生成器表达式具有my_function(a) for a in iterator 的形式,或者如果iterator 给我们返回两个元素tuples,如groupby 的情况:my_function(a,b) for a,b in iterator

    【讨论】:

    • 我得到一个错误 - df = pandas.read_csv(io.StringIO(data), delimiter='\s+') TypeError: initial_value must be unicode or None, not str @Pedro M Duarte跨度>
    【解决方案3】:

    没有什么比单线更好的了:

    In [145]:
    
    print df.groupby('name').describe().reset_index().pivot(index='name', values='score', columns='level_1')
    
    level_1  25%  50%  75%  count  max  mean  min       std
    name                                                   
    A        2.0    3  4.0      5    5     3    1  1.581139
    B        3.5    5  6.5      4    8     5    2  2.581989
    

    【讨论】:

      【解决方案4】:

      使用代码

      df.groupby('name').describe()
      

      【讨论】:

        【解决方案5】:

        表存储在名为df的数据框中

        df= pd.read_csv(io.StringIO(data),delimiter='\s+')
        

        只需指定列名,describe 即可为您提供所需的输出。通过这种方式,您可以计算 w.r.t 任何列

        df.groupby('name')['score'].describe()
        

        【讨论】:

          【解决方案6】:
          import pandas as pd
          import io
          import numpy as np
          
          data = """
          name score
          A      1
          A      2
          A      3
          A      4
          A      5
          B      2
          B      4
          B      6
          B      8
              """
          
          df = pd.read_csv(io.StringIO(data), delimiter='\s+')
          
          df2 = df.groupby('name').describe().reset_index().T.drop('name')
          arr = np.array(df2).reshape((4,8))
          
          df2 = pd.DataFrame(arr[1:], index=['name','A','B'])
          
          print(df2)
          

          这会给你 df2 为:

                        0     1        2    3    4    5    6    7
              name  count  mean      std  min  25%  50%  75%  max
              A         5     3  1.58114    1    2    3    4    5
              B         4     5  2.58199    2  3.5    5  6.5    8
          

          【讨论】:

            【解决方案7】:

            嗯,我设法得到了你想要的,但它的扩展性不是很好。

            import pandas as pd
            
            name = ['a','a','a','a','a','b','b','b','b','b']
            score = [1,2,3,4,5,2,4,6,8]
            
            d = pd.DataFrame(zip(name,score), columns=['Name','Score'])
            d = d.groupby('Name').describe()
            d = d.reset_index()
            df2 = pd.DataFrame(zip(d.level_1[8:], list(d.Score)[:8], list(d.Score)[8:]), columns = ['Name','A','B']).T
            
            print df2
            
                      0     1         2    3    4    5    6    7
            Name  count  mean       std  min  25%  50%  75%  max
            A         5     3  1.581139    1    2    3    4    5
            B         4     5  2.581989    2  3.5    5  6.5    8
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-11-29
              • 2018-07-17
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多