이번 포스팅에서는 Python pandas의 GroupBy()와 apply() 함수를 사용하여 그룹별로 무작위 표본 추출 (Random Sampling and Permutation by Groups) 하는 방법을 소개하겠습니다. 


무작위 표본 추출을 하는 데는 np.random.permutation() 함수를 사용해서 순열을 무작위로 뒤섞은 후에 n개 만큼 indexing 해오는 방법을 사용하였습니다. 



[ 그룹 별 무작위 표본 추출 (Random Sampling and Permutation by Groups) ]




먼저 예제로 사용한 'grp_1'과 'grp_2'의 두 개의 그룹을 포함한 DataFrame을 만들어보겠습니다. 



import numpy as np

import pandas as pd


# setting seed number for reproducibility

np.random.seed(123)


# Make a DataFrame

df = pd.DataFrame({'grp': ['grp_1']*10 + ['grp_2']*10, 

                          'col_1': np.random.randint(20, size=20), 

                          'col_2': np.random.randint(20, size=20)})

 

df

col_1col_2grp
01316grp_1
124grp_1
2217grp_1
363grp_1
4172grp_1
5197grp_1
6102grp_1
7115grp_1
8016grp_1
9177grp_1
10159grp_2
1193grp_2
1206grp_2
13141grp_2
1402grp_2
15151grp_2
161912grp_2
17148grp_2
1843grp_2
19010grp_2





사용자가 지정한 샘플링 비율(sample_pct) 만큼 무작위 표본 추출을 해주는 사용자 정의 함수 (User Defined Function)을 정의해보겠습니다. 



# UDF of random sampling

def sampling_func(data, sample_pct):

    np.random.seed(123)

    N = len(data)

    sample_n = int(len(data)*sample_pct) # integer

    sample = data.take(np.random.permutation(N)[:sample_n])

    return sample

 



이제 위의 무작위 샘플링 사용자 정의 함수(UDF)를 GroupBy()와 apply() 함수에 적용해서 그룹별 특정 비율(이 예에서는 80%)만큼 무작위 표본 추출(random sampling and permutation by groups)을 해보겠습니다.  



# Apply random sampling UDF to groups

sample_set = df.groupby('grp').apply(sampling_func, sample_pct=0.8)


sample_set.sort_index()

col_1col_2grp
grp
grp_101316grp_1
124grp_1
363grp_1
4172grp_1
5197grp_1
6102grp_1
7115grp_1
8016grp_1
grp_210159grp_2
1193grp_2
13141grp_2
1402grp_2
15151grp_2
161912grp_2
17148grp_2
1843grp_2

 



위의 무작위 표본 추출 결과에서 group_keys 를 없애려면 group_keys = False 를 지정해주면 됩니다. 



# disable group_keys

sample_set = df.groupby('grp', group_keys=False).apply(sampling_func, sample_pct=0.8)


sample_set.sort_index()

col_1col_2grp
01316grp_1
124grp_1
363grp_1
4172grp_1
5197grp_1
6102grp_1
7115grp_1
8016grp_1
10159grp_2
1193grp_2
13141grp_2
1402grp_2
15151grp_2
161912grp_2
17148grp_2
1843grp_2




위의 80% 무작위 샘플링이 된 sample_set 에 있는 데이터셋을 training_set 이라고 가정해보고, 위의 sample_set에는 없지만 원래 데이터에는 있던 나머지 20% 데이터를 test_set 으로 별도로 만들어보겠습니다. 



test_set = df.drop(df.index[sample_set.index])

test_set

col_1col_2grp
2217grp_1
9177grp_1
1206grp_2
19010grp_2

 



많은 도움이 되었기를 바랍니다. 


이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요. ^^



Posted by R Friend R_Friend