transform(‘mean’)の使い方
データセットはしばしば1人だけや1個だけではなく、代わりにいくつかのグループ化された構造を持っている時があります。これらのグループ化は、サブグループ(例えば、性別や年齢(層))やネスト構造(例えば、家族内の子供、または1人に対する複数の観測(時間が1年後、2年後など)を反映しているかもしれません。
今回はPythonでのサブグループの構造を見てみましょう。
まずはpandas
とnumpy
をインポートして、データセットを読み込んでみましょう。
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
という結果でも同じく平均が求められます。