LoginSignup
17
14

More than 5 years have passed since last update.

pandas クロス集計でユニーク値の総計を求める

Last updated at Posted at 2016-11-01

目的

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

参考

17
14
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
14