【エコンティア】経済学・データサイエンス
 
ECONTIER

【Python】groupby(”)[”].transform(‘mean’) – グルーピングの平均

transform(‘mean’)の使い方

データセットはしばしば1人だけや1個だけではなく、代わりにいくつかのグループ化された構造を持っている時があります。これらのグループ化は、サブグループ(例えば、性別や年齢(層))やネスト構造(例えば、家族内の子供、または1人に対する複数の観測(時間が1年後、2年後など)を反映しているかもしれません。

今回はPythonでのサブグループの構造を見てみましょう。

まずはpandasnumpyをインポートして、データセットを読み込んでみましょう。

GitHubに載せているcsvデータをここでは利用します。

取り込むときはpandasでCSVをデータフレームで読み込むpd.read_csvを使います。

 

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') 


print(df[['no','personid', 'studyhour', 'av_study']])

 

出力

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はpersonidが1の同一生徒として考えます。

その場合2022/1/7では勉強時間1時間、2022/1/8では勉強時間が4時間となり、

生徒1(personidが1)の勉強の平均時間は2.5時間です。これをPythonで求めてみましょう。

それぞれの生徒をまずはグルーピングして、平均を取る場合は、

Pandasの関数であるgroupbyでは、groupby().transform()を利用できます。

下記のコードでは

df[‘av_study’] = df.groupby(‘personid’)[‘studyhour’].transform(‘mean’)

としています。personidをグルーピングし、studyhourをmeanで平均を出しています。

 

# personidでグループ化してstudyhourの平均を計算 
df['av_study'] = df.groupby('personid')['studyhour'].transform('mean') 

# personidでソートして結果を表示 
df = df.sort_values('personid') 

print(df[['no','personid', 'studyhour', 'av_study']])

 

 

 

下記で出力結果を見てみましょう。

出力

print(df[[‘no’,’personid’,’dt’, ‘studyhour’, ‘av_study’]])

no personid dt studyhour av_study
1 1 2022/1/7 1 2.5
2 1 2022/1/8 4 2.5
3 2 2022/1/16 8 6.666667
4 2 2022/1/18 3 6.666667
5 2 2022/1/19 9 6.666667
6 3 2022/1/21 1 4.666667
7 3 2022/1/22 6 4.666667
8 3 2022/1/10 7 4.666667
9 4 2022/1/11 4 4.5
10 4 2022/1/13 5 4.5

no1と2は、ともにpersonidが1の生徒で、2022/1/7での勉強時間が1(時間)で、2022/1/8での勉強時間が4(時間)なので(1+4)/2となり平均の2.5(時間)がno1とno2でともに2.5が入力されます。

その他でも、no3、no4、no5がpersonid2の生徒で(8+3+9)/3=6.666667

no6、no7、no8のpersonid3が(1+6+7)/3=4.666667

no9、no10のpersonid4が(4+5)/2=4.5

となっているのが確認できます。

 

また下記での表記での結果でも表せます。

df_listing = df.groupby("personid")
df_listing["studyhour"].mean()

出力結果は、

personid
1 2.500000
2 6.666667
3 4.666667
4 4.500000
Name: studyhour, dtype: float64

という結果でも同じく平均が求められます。