2017-10-14 10 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=', ') + apply', '.join(x.astype(str))

1

オプション1
strプレ変換+ groupbyと同様です。

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 

だけでなく、元のデータフレームを修正することのマイナス面で。

パフォーマンス.assign方法はこれよりわずか数ミリ秒遅いこと

# 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

注意。大規模なデータフレームでは、より大きなパフォーマンス向上が見られるはずです。


オプション2
groupby + 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 

そしてこれのインプレースバージョンは上記と同じである:

同様の動作がaggと続きます。

# 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よりも速度の向上が表示されるはずです。

関連する問題