pandasのgroupbyで特徴量を作りたい
カラムの属性ごとの統計量を特徴に追加したいときに,collectionsやgroupbyでdictみたいなの作ってマージしなくても良い場合が結構あります.
単に統計量出すだけであれば簡単なものの,特徴量としてレコードに追加したい局面にpandas.DataFrame.groupbyの使い方に苦戦したのでメモとして残します.
何が言いたいかというとgroupby.transformは便利.
サンプルデータ
import pandas as pd
df = pd.DataFrame({
"site":["A","A","A","B","B","C"],
"dat":[15,30,30,30,10,50]
})
site | dat | |
---|---|---|
0 | A | 15 |
1 | A | 30 |
2 | A | 30 |
3 | B | 30 |
4 | B | 10 |
5 | C | 50 |
属性ごとの平均,最大,最小など基本統計量
transformの引数をnp.maxやnp.minに変えれば直接特徴量が生成できる.
median, varなども同様.
siteごとの平均値を算出するコードを下に示す.
import numpy as np
df["site_mean"] = df.groupby("site").transform(np.mean)
site | dat | site_mean | |
---|---|---|---|
0 | A | 15 | 25 |
1 | A | 30 | 25 |
2 | A | 30 | 25 |
3 | B | 30 | 20 |
4 | B | 10 | 20 |
5 | C | 50 | 50 |
Count Encoding
あるカラムの(カテゴリ)特徴の出現回数を新たな特徴にする手法がカウントエンコーディングと呼ばれている.groupbyと組み合わせることで,ある属性の中での希少性のようなものを特徴にできる.
collections.Counter使えばできますが,これも同じくtransformで終わらせます.
siteとdatのペアの出現回数に変換するコードを示す.
(site Aにおける30の出現回数は2回)
df["count_site_dat"] = df.groupby(["site","dat"]).transform(np.size)
site | dat | site_mean | count_size_dat | |
---|---|---|---|---|
0 | A | 15 | 25 | 1 |
1 | A | 30 | 25 | 2 |
2 | A | 30 | 25 | 2 |
3 | B | 30 | 20 | 1 |
4 | B | 10 | 20 | 1 |
5 | C | 50 | 50 | 1 |
順位
ある特徴を持っているデータの中で,ある特徴が何番目に大きいデータかを算出する.
df["site_rank"] = df.groupby("site")["dat"].rank(method="dense")
site | dat | site_mean | count_size_dat | site_rank | |
---|---|---|---|---|---|
0 | A | 15 | 25 | 1 | 1 |
1 | A | 30 | 25 | 2 | 2 |
2 | A | 30 | 25 | 2 | 2 |
3 | B | 30 | 20 | 1 | 2 |
4 | B | 10 | 20 | 1 | 1 |
5 | C | 50 | 50 | 1 | 1 |
rankの引数を変えると,主に同じ値(同じ順位)の表現方法が変わる.
詳細はpandas.DataFrame, Seriesを順位付けするrankのmethodを参照.