【问题标题】:Create a pivot table that lists out values创建一个列出值的数据透视表
【发布时间】:2018-03-26 09:34:50
【问题描述】:

我需要使用什么 aggfunc 来使用数据透视表生成列表?我尝试使用 str ,但效果不太好。

输入

import pandas as pd
data = {
    'Test point': [0, 1, 2, 0, 1],
    'Experiment': [1, 2, 3, 4, 5]
}
df = pd.DataFrame(data)
print df

pivot = pd.pivot_table(df, index=['Test point'], values=['Experiment'], aggfunc=len)
print pivot

pivot = pd.pivot_table(df, index=['Test point'], values=['Experiment'], aggfunc=str)
print pivot

输出

   Experiment  Test point
0           1           0
1           2           1
2           3           2
3           4           0
4           5           1
            Experiment
Test point            
0                    2
1                    2
2                    1
                                                Experiment
Test point                                                
0           0    1\n3    4\nName: Experiment, dtype: int64
1           1    2\n4    5\nName: Experiment, dtype: int64
2                   2    3\nName: Experiment, dtype: int64

期望的输出

            Experiment
Test point                                                
0           1, 4
1           2, 5
2           3

【问题讨论】:

    标签: python pandas pivot-table


    【解决方案1】:

    您可以将list 本身用作函数:

    >>> pd.pivot_table(df, index=['Test point'], values=['Experiment'], aggfunc=lambda x:list(x))
               Experiment
    Test point           
    0              [1, 4]
    1              [2, 5]
    2                 [3]
    

    【讨论】:

      【解决方案2】:

      使用

      In [1830]: pd.pivot_table(df, index=['Test point'], values=['Experiment'],
                                aggfunc=lambda x: ', '.join(x.astype(str)))
      Out[1830]:
                 Experiment
      Test point
      0                1, 4
      1                2, 5
      2                   3
      

      或者,groupby 可以。

      In [1831]: df.groupby('Test point').agg({
                      'Experiment': lambda x: x.astype(str).str.cat(sep=', ')})
      Out[1831]:
                 Experiment
      Test point
      0                1, 4
      1                2, 5
      2                   3
      

      但是,如果你想要那么作为列表。

      In [1861]: df.groupby('Test point').agg({'Experiment': lambda x: x.tolist()})
      Out[1861]:
                 Experiment
      Test point
      0              [1, 4]
      1              [2, 5]
      2                 [3]
      

      x.astype(str).str.cat(sep=', ') 类似于', '.join(x.astype(str))

      【讨论】:

        【解决方案3】:

        选项 1
        str 预转换 + groupby + apply

        您可以预先转换为字符串以简化groupby 调用。

        df.assign(Experiment=df.Experiment.astype(str))\
              .groupby('Test point').Experiment.apply(', '.join).to_frame('Experiment')
        
                   Experiment
        Test point           
        0                1, 4
        1                2, 5
        2                   3
        

        为了速度,对此的修改将涉及就地分配(assign 返回一个副本并且速度较慢):

        df.Experiment = df.Experiment.astype(str)
        df.groupby('Test point').Experiment.apply(', '.join).to_frame('Experiment')
        
                   Experiment
        Test point           
        0                1, 4
        1                2, 5
        2                   3
        

        还有修改原始数据框的缺点。

        性能

        # Zero's 1st solution
        %%timeit
        df.groupby('Test point').agg({'Experiment': lambda x: x.astype(str).str.cat(sep=', ')})
        
        100 loops, best of 3: 3.72 ms per loop
        
        # Zero's second solution
        %%timeit
        pd.pivot_table(df, index=['Test point'], values=['Experiment'], 
                       aggfunc=lambda x: ', '.join(x.astype(str)))
        
        100 loops, best of 3: 5.17 ms per loop
        
        # proposed in this post
        %%timeit -n 1
        df.Experiment = df.Experiment.astype(str)
        df.groupby('Test point').Experiment.apply(', '.join).to_frame('Experiment')
        
        1 loop, best of 3: 2.02 ms per loop

        请注意,.assign 方法只比这慢几毫秒。更大的数据帧应该会看到更大的性能提升。


        选项 2
        groupby + agg:

        agg 进行类似的操作:

        df.assign(Experiment=df.Experiment.astype(str))\
                 .groupby('Test point').agg({'Experiment' : ', '.join})
        
                   Experiment
        Test point           
        0                1, 4
        1                2, 5
        2                   3
        

        并且它的就地版本将与上述相同。

        # proposed in this post
        %%timeit -n 1
        df.Experiment = df.Experiment.astype(str)
        df.groupby('Test point').agg({'Experiment' : ', '.join})
        
        1 loop, best of 3: 2.21 ms per loop

        agg 对于更大的数据帧,速度应该会超过apply

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-08-20
          • 1970-01-01
          • 1970-01-01
          • 2019-11-07
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多