2017-10-14 91 views
8

需要使用數據透視表生成列表時需要使用什麼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 

回答

2

可以使用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] 
7

使用

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))

1

選項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較大dataframes。