使い方 – groupby(”)[”].transform(‘sum / min / max’)
今回は、Pandasライブラリでのgroupby関数で、グループ内での合計、最小値、最大値を算出します。
【Python】groupby(”)[”].transform(‘mean’) – グルーピングの平均 と同じデータセットを利用します。
import pandas as pd import numpy as np # CSVファイルを読み込む df = pd.read_csv('https://raw.githubusercontent.com/econtier/sitedata/main/workprint(df[['no','personid', 'studyhour', 'av_study']])ingstudying.csv')
出力
no | personid | dt | male | workhour | studyhour |
1 | 1 | 2022/1/7 | 1 | 4 | 1 |
2 | 1 | 2022/1/8 | 1 | 5 | 4 |
3 | 2 | 2022/1/16 | 0 | 2 | 8 |
4 | 2 | 2022/1/18 | 0 | 4 | 3 |
5 | 2 | 2022/1/19 | 0 | 1 | 9 |
6 | 3 | 2022/1/21 | 1 | 3 | 1 |
7 | 3 | 2022/1/22 | 1 | 5 | 6 |
8 | 3 | 2022/1/10 | 1 | 8 | 7 |
9 | 4 | 2022/1/11 | 0 | 9 | 4 |
10 | 4 | 2022/1/13 | 0 | 10 | 5 |
ここでは、 最初のnoは通し番号、personidは生徒番号としましょう。
dtは年/月/日を表します。 maleは性別で、1=男性、0=女性を表します(ダミー変数)。
workhourはアルバイト時間(◯時間)、studyhourは勉強時間(◯時間)とします。
表の見方としては、 no1とno2は同一人物でpersonidが1の生徒のデータになります。
この生徒1は、 2022/1/7にアルバイトに4時間、勉強に1時間、
2022/1/8にアルバイトに5時間、勉強に4時間、
をしたことが観察されます。
各サブグループの合計、最小値、最大値
合計
まずはサブグループの合計を求めてみましょう。
ここでのサブグループはネスト構造としてのある1人に対して複数の観察期間がある事になっています。
つまり先程の通し番号noでの1と2はpersonid1で同一生徒として考えます。
その場合、
2022/1/7では勉強時間1時間、2022/1/8では勉強時間が4時間となり、
personid1生徒の合計勉強時間は5時間になります。
最小値
personid1での期間での最小値は、
2022/1/7では勉強時間1時間、2022/1/8では勉強時間が4時間ですので
最小値は1時間となります。
最大値
personid1での期間での最大値は、
2022/1/7では勉強時間1時間、2022/1/8では勉強時間が4時間ですので
最大値は4時間となります。
それでは
それぞれの生徒をまずはグルーピングして、合計、最小値、最大値を取る場合は、
Pandasの関数であるgroupbyでは、groupby().transform()を利用できます。
下記のコードでは合計、最小値、最大値を表せます。
df[‘study_total’] = df.groupby(‘personid’)[‘studyhour’].transform(‘sum’)
df[‘study_min’] = df.groupby(‘personid’)[‘studyhour’].transform(‘min’)
df[‘study_max’] = df.groupby(‘personid’)[‘studyhour’].transform(‘max’)
# personidでグループ化してstudyhourの合計、最小値、最大値を計算 df['study_total'] = df.groupby('personid')['studyhour'].transform('sum') df['study_min'] = df.groupby('personid')['studyhour'].transform('min') df['study_max'] = df.groupby('personid')['studyhour'].transform('max') # personidとstudy*列を表示 df = df.sort_values('personid') print(df[['personid', 'studyhour','study_total', 'study_min', 'study_max']])
出力
no | personid | studyhour | study_total | study_min | study_max |
1 | 1 | 1 | 5 | 1 | 4 |
2 | 1 | 4 | 5 | 1 | 4 |
3 | 2 | 8 | 20 | 3 | 9 |
4 | 2 | 3 | 20 | 3 | 9 |
5 | 2 | 9 | 20 | 3 | 9 |
6 | 3 | 1 | 14 | 1 | 7 |
7 | 3 | 6 | 14 | 1 | 7 |
8 | 3 | 7 | 14 | 1 | 7 |
9 | 4 | 4 | 9 | 4 | 5 |
10 | 4 | 5 | 9 | 4 | 5 |
出力結果を見てみます。
personid1の勉強時間の合計は5、最小値は1、最大値は4
personid2の勉強時間の合計は20、最小値は3、最大値は9
personid3の勉強時間の合計は14、最小値は1、最大値は7
personid4の勉強時間の合計は9、最小値は4、最大値は5
となります。
また、personidをグルーピングをより分かりやすくするため以下のコードでGroupごとで確認できます。
df = df.sort_values('personid') groups = df.groupby('personid') for group_name, group_df in groups: print(f"Group: {group_name}") print(group_df.filter(['no','studyhour','study_total','study_min', 'study_max'])) print()
出力
このようにGroup:1〜Group:4で分けながら表記することができます。
Group:1 | ||||
no | studyhour | study_total | study_min | study_max |
1 | 1 | 5 | 1 | 4 |
2 | 4 | 5 | 1 | 4 |
Group:2 | ||||
no | studyhour | study_total | study_min | study_max |
3 | 8 | 20 | 3 | 9 |
4 | 3 | 20 | 3 | 9 |
5 | 9 | 20 | 3 | 9 |
Group:3 | ||||
no | studyhour | study_total | study_min | study_max |
6 | 1 | 14 | 1 | 7 |
7 | 6 | 14 | 1 | 7 |
8 | 7 | 14 | 1 | 7 |
Group:4 | ||||
no | studyhour | study_total | study_min | study_max |
9 | 4 | 9 | 4 | 5 |
10 | 5 | 9 | 4 | 5 |
また下記での表記での結果でも表せます。
合計
df_total = df.groupby("personid") df_listing["studyhour"].sum()
出力
personid
1 4
2 9
3 7
4 5
Name: studyhour, dtype: int64
最小値
df_min = df.groupby("personid") df_listing["studyhour"].min()
出力
personid
1 1
2 3
3 1
4 4
Name: studyhour, dtype: int64
最大値
df_max = df.groupby("personid") df_listing["studyhour"].max()
出力
personid
1 4
2 9
3 7
4 5
Name: studyhour, dtype: int64
という結果でも同じく合計、最小値、最大値が求められます。