Mar 28, 2019

Pandasのpivotとpivot_tableの違いについて

この間、Pandasの勉強をしていると、PandasのDataFrameクラスにはpivotとpivot_tableという2つのメソッドがあることに気付かず、違う方を使って自分で打ち込んだサンプルコードが動かなかったり、helpを読んで混乱することが度々あった。
pivotとpivot_tableが違うことに気付いた時にあまりにも悔しかったので、pivotとpivot_tableの違いに関してメモしておく。

以下、Jupyter Notebookで書いたコードと出力を使って記述する。

In [1]:
df = pd.DataFrame({'date': ['{}:{:02d}:{:02d}'.format(6, 30, s) for s in (2, 2, 2, 3, 3, 3, 4, 4, 4)],
                    'variable': ['A', 'B', 'C'] * 3,
                    'value': list('abcdefghi')})

df
Out [1]:
date variable value
0 6:30:02 A a
1 6:30:02 B b
2 6:30:02 C c
3 6:30:03 A d
4 6:30:03 B e
5 6:30:03 C f
6 6:30:04 A g
7 6:30:04 B h
8 6:30:04 C i

こういう、いわゆるlongフォーマットの時系列データを以下のwideフォーマットに変形することを考える。(筆者は最近実際にやることがあった)

In [2]:
df.pivot(index='date', columns='variable', values='value')
Out [2]:
variable A B C
date
6:30:02 a b c
6:30:03 d e f
6:30:04 g h i

上ではpivotを使ったが、pivot_tableを使っても同じことができる。
但し、pivot_tableはグループ毎(2次元の表にまとめられたセル毎)に集約関数が適用され、defaultの関数はnp.sumで、この例のようにセルの値が文字列だと適用できず、"DataError: No numeric types to aggregate"というエラーになる為、何か文字列を受け取れる関数を指定する必要がある。
(下記のようにaggfunc='first'とすると、DataFrameGroupBy.firstが用いられると思われる)

In [3]:
df.pivot_table(index='date', columns='variable', values='value', aggfunc='first')
Out [3]:
variable A B C
date
6:30:02 a b c
6:30:03 d e f
6:30:04 g h i

このように、pivot_tableはグループ毎に必ず集約関数が使われるのが、pivotとの主な違いのようである。
pivotでは集約ができないので、次のように結果が同じ行と同じ列に相当する行があると、それらが全く同じ値であってもエラーになる。(筆者は実際にそういうデータに遭遇して難儀した)

In [4]:
df = df.append(pd.DataFrame({'date': ['{}:{:02d}:{:02d}'.format(6, 30, s) for s in (6, 6, 6) * 2],
                    'variable': ['A', 'B', 'C'] * 2,
                    'value': list('jkl') * 2}))
df
Out [4]:
date variable value
0 6:30:02 A a
1 6:30:02 B b
2 6:30:02 C c
3 6:30:03 A d
4 6:30:03 B e
5 6:30:03 C f
6 6:30:04 A g
7 6:30:04 B h
8 6:30:04 C i
0 6:30:06 A j
1 6:30:06 B k
2 6:30:06 C l
3 6:30:06 A j
4 6:30:06 B k
5 6:30:06 C l
In [5]:
df.pivot(index='date', columns='variable', values='value')
Out [5]:
ValueError: Index contains duplicate entries, cannot reshape

pivot_tableであれば、この場合も成功する。

In [6]:
df.pivot_table(values='value', index='date', columns='variable', aggfunc='first')
Out [6]:
variable A B C
date
6:30:02 a b c
6:30:03 d e f
6:30:04 g h i
6:30:06 j k l

See more ...

Posted at 20:35 in PC一般 | WriteBacks (0)
WriteBacks