ランダムの森

20代エンジニアです。プログラミングについて主に書いてます。

pandasのDataFrameで分位点で5つに分割しグループ分けするやり方。

分位点については以下で説明しています。
dorei-kaiho.hatenablog.com

今回は分位点による4分割ではなくあえて(深い意味はありません)5分割のグループ分けをしたいと思います。

まずはデータを用意します。
データフレームはインデックス名をa〜uまで振っています。

import numpy as np
import pandas as pd
from pandas import DataFrame

data = np.random.randint(1,100,20)
data

output > array([61, 29, 19, 15, 54, 8, 20, 27, 27, 85, 71, 37, 63, 84, 50, 46, 11, 20, 36, 93])

df= DataFrame(data
                ,index = ['a','b','c','d','e','f','h','i','j','k','l','m','n','o','p','q','r','s','t','u']
                ,columns = ['values']
                           )
df.index.names = ['names']
df.head()

output >
f:id:doreikaiho:20181208224644p:plain

ここからグループ分けの準備します。
今回は5分割するので、まずはbinsというリストに以下の境界線にくる各分位点を格納します。
[0%, 20%, 40%, 60%, 80%]

df['values'].quantile(x)はxの境界線にくる分位点を取ってきます。
例えばdf['values'].quantile(0.5)は中央値を取ってきます。
一番小さい値を確実に拾うため、binsには0を先に入れています。

bins = [0]
for i in range(1,6):
    bins.append(df['values'].quantile(0.2 * i))
bins

output > [0, 19.8, 28.200000000000003, 47.60000000000001, 64.60000000000001, 93.0]

次に、binsに格納した各分位点を基にしてcutによってグループ分けします。
labels = group_namesによって各グループに名前をつけます。

group_names = ['first', "second", "third", "fourth",'fifth']
group = pd.cut(df['values'],bins,labels = group_names)
df['group'] = group
df

output >
f:id:doreikaiho:20181208230945p:plain

最後に同じグループ同士をまとめてソートします。
あえて、get_group(group)でグループごとにデータフレームを取り出してconcatで再結合しました。
そのためvalueのcolumnは完全にはソートされていません。

df_grouped = pd.DataFrame([])
for group in group_names:
    df_grouped = pd.concat([df_grouped,df.groupby('group').get_group(group)])

output >
f:id:doreikaiho:20181208230237p:plain