今回は、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/workingstudying.csv') print(df)
出力
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時間、
をしたことが観察されます。
各サブグループの標準偏差
ここでは各サブグループでの標本標準偏差と母標準偏差を出してみましょう。
それぞれの生徒をまずはグルーピングして、勉強時間の標本標準偏差と母標準偏差を取る場合は、
Pandasの関数であるgroupbyでは、groupby().transform()を利用できます。
下記のコードでは標準偏差を表すコードとして
df[‘sd_study’] = df.groupby(‘personid’)[‘studyhour’].transform(‘std’)
というコードができます。
もう少し具体的に言うと、
df[‘sd_study’] = df.groupby(‘personid’)[‘studyhour’].transform(‘std’)
は、標本標準偏差を表し、
df[‘sd_study2’] = df.groupby(‘personid’)[‘studyhour’].transform(lambda x: x.std(ddof=0))
と、後ろに(lambda x: x.std(ddof=0))を置くことで、母標準偏差を出すことが出来ます。
# personidでグループ化してstudyhourの平均を計算 df['av_study'] = df.groupby('personid')['studyhour'].transform('mean') # personidでグループ化してstudyhourの標準偏差を計算 df['sd_study'] = df.groupby('personid')['studyhour'].transform('std') df['sd_study2'] = df.groupby('personid')['studyhour'].transform(lambda x: x.std(ddof=0)) df = df.sort_values('personid') groups = df.groupby('personid') for group_name, group_df in groups: print(f"Group: {group_name}") print(group_df[['personid', 'studyhour', 'av_study', 'sd_study','sd_study2']]) print()
出力
Group: 1 | ||||
personid | studyhour | av_study | sd_study | sd_study2 |
1 | 1 | 2.5 | 2.12132 | 1.5 |
1 | 4 | 2.5 | 2.12132 | 1.5 |
Group: 2 | ||||
personid | studyhour | av_study | sd_study | sd_study2 |
2 | 8 | 6.666667 | 3.21455 | 2.624669 |
2 | 3 | 6.666667 | 3.21455 | 2.624669 |
2 | 9 | 6.666667 | 3.21455 | 2.624669 |
Group: 3 | ||||
personid | studyhour | av_study | sd_study | sd_study2 |
3 | 1 | 4.666667 | 3.21455 | 2.624669 |
3 | 6 | 4.666667 | 3.21455 | 2.624669 |
3 | 7 | 4.666667 | 3.21455 | 2.624669 |
Group: 4 | ||||
personid | studyhour | av_study | sd_study | sd_study2 |
4 | 4 | 4.5 | 0.707107 | 0.5 |
4 | 5 | 4.5 | 0.707107 | 0.5 |
出力結果を見てみます。
標本標準偏差はsd_studyですので
personid1が2.12132、personid2が3.21455、personid3が3.21455、personid4が0.707107となります。
母標準偏差はsd_study2ですので
personid1が1.5、personid2が2.624669、personid3が2.624669、personid4が0.5となります。
また下記での表記での結果でも表せます。
df_sdv = df.groupby("personid") df_sdv["studyhour"].std()
df_sdv = df.groupby(“personid”)
df_sdv[“studyhour”].std()
Out[26]:
personid
1 2.121320
2 3.214550
3 3.214550
4 0.707107
Name: studyhour, dtype: float64
df_sdv2 = df.groupby("personid") df_sdv2["studyhour"].std(ddof=0)
df_sdv2 = df.groupby(“personid”)
df_sdv2[“studyhour”].std(ddof=0)
Out[27]:
personid
1 1.500000
2 2.624669
3 2.624669
4 0.500000
Name: studyhour, dtype: float64