###目的
pandasで2つのカテゴリ変数でvalue変数をクロス集計し、value変数のユニーク値の総計を求めたい。
###SQLで書くと以下のコード
SELECT date,carrier,count(DISTINCT host) as cnt
FROM apachelog
GROUP BY date,carrier;
集計イメージ
date とcarrier変数(カテゴリはAndroid,iOS,Otherの3種類)ごとに、変数hostのユニーク値をカウント
date | Android | iOS | Other |
---|---|---|---|
2015/04/01 | 5000 | 1300 | 15 |
2015/04/02 | 5200 | 1230 | 16 |
2015/04/03 | 5300 | 1100 | 17 |
... | ... | ... | ... |
python3でのコード(1) pivot_tableメソッドを使う
クロス集計(カラムB×カラムC)の各セルごとのカラムAの平均値
pd.pivot_table(df,value='A',index='B',columns='C')
クロス集計(カラムB×カラムC)の各セルごとのカラムAの個数
pd.pivot_table(df,value='A',index='B',columns='C',aggfunc = 'count')
クロス集計(カラムB×カラムC)の各セルごとのカラムAの総計
pd.pivot_table(df,value='A',index='B',columns='C',aggfunc = 'sum')
では、各セルごとのカラムAのユニークな値の個数はどうするか?
lambda式を使います。
lambda式の書き方は、lambda 引数1,引数2 ・・・ :処理
pivot_unique.py
import pandas as pd
#データはpandasのデータフレームにしておく
df = pd.DataFrame(apachlog)
#以下のやり方ではna値を含んだ値になります。
#あらかじめデータフレーム.info()でnaがないと分かっている時には使える手
pv = pd.pivot_table(df, values='host',index = 'date',columns = 'carrier',
aggfunc = lambda x:len(x.unique()))
#以下のやり方は、na値を除いた値になります。
pv = pd.pivot_table(df, values='host',index = 'date',columns = 'carrier',
aggfunc = lambda x:x.nunique())
(おまけ)ファイルにエクスポート
pandasのデータフレームはto_csvメソッドでtsv形式でエクスポートできます。
output.py
fout = 'output.tsv'
f = open(fout,'w',encoding = 'utf-8')
pv.to_csv(fout,sep = '\t')
f.close()
python3でのコード(2) groupbyメソッドを使う
use_groupby.py
#x軸、y軸を指定してグループバイオブジェクトを作る
grouped = df.groupby(['date','carrier'])
#データフレームにgroupbyしても結果が出てくるのではなく、集約キーが付与されたデータフレームのGroupByオブジェクトが生成されるだけ
#groupedオブジェクトに対して、カラム「host」で集約する。
#集約する関数は、agg(この中身をラムダ式で指定)
#naもユニーク値に含まれるカウント
grouped.host.agg(lambda x: len(x.unique()))
#naを含まないカウント
grouped.host.agg(lambda x: x.nunique())
groupbyメソッドの集計結果は、「縦持ち」(=long型)テーブルになります。
date | carrier | |
---|---|---|
2015/04/01 | Android | 5000 |
2015/04/01 | iOS | 1300 |
2015/04/01 | Other | 15 |
2015/04/02 | Android | 5200 |
... | ... | ... |
「縦持ち」(long型)をクロス型(?というのでしょうか?)(=wide型)に展開したい場合、以下のようにunstackメソッドを使えば、上の集計イメージを得られます。
#g = grouped.host.agg(lambda x: len(x.unique()))
g = grouped.host.agg(lambda x: x.nunique()))
g.unstack()
実行環境
- anaconda3-4.0.0
- OS X El Capitan 10.11.3
###参考