はてだBlog(仮称)

私的なブログど真ん中のつもりでしたが、気づけばWebサイト系のアプリケーション開発周りで感じたこと寄りの自分メモなどをつれづれ述べています。2020年6月現在、Elasticsearch、pandas、CMSなどに関する話題が多めです。...ですが、だんだんとより私的なプログラムのスニペット置き場になりつつあります。ブログで述べている内容は所属組織で販売している製品などに関するものではなく、また所属する組織の見解を代表するものではありません。

Pandas pivot、pivot_table、melt、stack、wide_to_longのシェイプ変更のイメージ(tidyデータ)

PandasにおけるDataFrameのシェイプ変更のメソッドである、 pivot、pivot_table、melt、stack、wide_to_longについて、これらをまとめて図解してみました。

f:id:azotar:20200225215358p:plain

実例

import pandas as pd
import io

df = pd.read_csv(io.StringIO("""
year,season,num
2010,春,4
2010,夏,1
2010,秋,2
2011,春,3
2011,夏,4
2012,春,1
2012,冬,2
""" ))

## pivot
_ = df.pivot(index='year', columns='season', values='num')
_
_.index


## pivot_table
import numpy as np
_ = pd.pivot_table(data=df,index='year', columns='season', aggfunc=len) # lenは欠損値の場合カウントしないので注意。
_
type(_)  # pandas.core.frame.DataFrame

_ = pd.pivot_table(data=df,index=['year'], columns=['season'], aggfunc=[np.max,np.min,np.mean])
_
type(_)  # pandas.core.frame.DataFrame
type(_.index)
type(_.columns) # -> pandas.core.indexes.multi.MultiIndex   ※ index、columns、aggfuncどれかに配列を指定した場合、MultiIndexになる。

# columnsがMultiIndexの場合(でも)、DataFrame.columnsに直接、件数を合わせた配列を代入してやれば、通常のインデックスになる↓
_.columns = ['_'.join(i) for i in _.columns]
_
type(_.columns)


## 
df = pd.read_csv(io.StringIO("""
year,春,夏,秋,冬
2010,1,2,3,4
2011,5,6,7,8
2012,9,10,11,12
""" ))

## melt
_ = df.melt(id_vars='year', var_name='季節', value_name='値')
_


## stack
_ = df.stack()

type(_) # -> pandas.core.series.Series
_.index


##  wide_to_long

df = pd.read_csv(io.StringIO("""
id,A111,A222,B111,C222,X
0,1,2,3,4,5
1,2,4,6,8,10
2,3,6,9,12,15
""" ))

pd.wide_to_long(df,stubnames=['A','B','C'], i='id',j='threechars') # stubnamesに「_」を使う時は注意

ひとつずつ分解した例

1-1. サンプルインプットデータ1

In [298]: 
     ...:  
     ...: df = pd.read_csv(io.StringIO(""" 
     ...: year,season,num 
     ...: 2010,春,4 
     ...: 2010,夏,1 
     ...: 2010,秋,2 
     ...: 2011,春,3 
     ...: 2011,夏,4 
     ...: 2012,春,1 
     ...: 2012,冬,2 
     ...: """ ))                                                                                                                             

1-2. pivot

In [299]: 
     ...: _ = df.pivot(index='year', columns='season', values='num') 
     ...: _                                                                                                                                  
Out[299]: 
season    冬    夏    春    秋
year                      
2010    NaN  1.0  4.0  2.0
2011    NaN  4.0  3.0  NaN
2012    2.0  NaN  1.0  NaN

In [300]:                                                                                                                                    

1-3. pivot_table

pivot_tableは集計。 位置付けからすると、重複データを扱える。

In [300]: 
     ...: import numpy as np 
     ...: _ = pd.pivot_table(data=df,index='year', columns='season', aggfunc=len) # lenは欠損値の場合カウントしないので注意。 
     ...: _                                                                                                                                  
Out[300]: 
        num               
season    冬    夏    春    秋
year                      
2010    NaN  1.0  1.0  1.0
2011    NaN  1.0  1.0  NaN
2012    1.0  NaN  1.0  NaN

2-1. サンプルインプットデータ2

In [301]:  
     ...: 
     ...: df = pd.read_csv(io.StringIO(""" 
     ...: year,春,夏,秋,冬 
     ...: 2010,1,2,3,4 
     ...: 2011,5,6,7,8 
     ...: 2012,9,10,11,12 
     ...: """ )) 
     ...:                                                                                                                                    

In [302]:                                                                                                                                    

## 2-2. melt

In [302]:
     ...: _ = df.melt(id_vars='year', var_name='季節', value_name='値') 
     ...: _ 
     ...:                                                                                                                                    
Out[302]: 
    year 季節   値
0   20101
1   20115
2   20129
3   20102
4   20116
5   201210
6   20103
7   20117
8   201211
9   20104
10  20118
11  201212

2-3. stack

In [303]: 
     ...: _ = df.stack() 
     ...:                                                                                                                                    

In [304]: _                                                                                                                                  
Out[304]: 
0  year    20101234
1  year    20115678
2  year    20129101112
dtype: int64

In [305]:                                                                                                                                    

2-4. wide_to_long

In [305]: 
     ...:  
     ...: df = pd.read_csv(io.StringIO(""" 
     ...: id,A111,A222,B111,C222,X 
     ...: 0,1,2,3,4,5 
     ...: 1,2,4,6,8,10 
     ...: 2,3,6,9,12,15 
     ...: """ ))                                                                                                                             

In [306]:                                                                                                                                    

In [306]: pd.wide_to_long(df,stubnames=['A','B','C'], i='id',j='threechars')                                                                 
Out[306]: 
                X  A    B     C
id threechars                  
0  111          5  1  3.0   NaN
   222          5  2  NaN   4.0
1  111         10  2  6.0   NaN
   222         10  4  NaN   8.0
2  111         15  3  9.0   NaN
   222         15  6  NaN  12.0

公式サイト

pandas.pydata.org

関連別記事

itdepends.hateblo.jp