잠깐 잠잠했던 확산을 뒤로하고, 다시금 COVID-19의 확산이 활발히 진행되고 있음에 따라, 전 세계가 코로나바이러스 확산을 최소화 하기 위해 최선을 다하고 있다. 확산을 최소화 하기 위해서는 정확한 요인을 파악하여 대처해야 한다. 캐글(Kaggle)에서 COVID19 Global Forecasting (Week 1) 같은 Challenge를 발표한 사례도 있다. 내가 주목한 부분은 국가별로 확진자수가 다르다는 점이다. 물론 국가별로 다를 수 있는 요소들에 다양할 수가 있지만, 예를 들어 국가별 대응 정책, 국민의 성향, 정부와의 신뢰관계 등이 있다. 내가 선택한 요인으로는 국가별 성향이 코로나바이러스 확산과 관계가 있을 수 있다고 생각했다. 따라서, K-means clustering을 활용하여 비슷한 성향을 가진 국가들의 코로나 확진자수의 관계를 확인해보자.
1.1 Big Five Personality Test
국가별 성향을 확인하기위해서 캐글에 있는 빅 파이브 성격테스트를 사용하였다. 한국을 예를 들면, 다음과 같다. 캐글에 빅 파이브 성격테스트에서 한국인 국적을 가진 사람들의 데이터를 모아서, 평균을 내어 한국의 성향으로 분석을 하였다. 빅 파이브 성격테스트에 대해서 간단히 알아보면, 기본적으로 설문지에 대답하는 형식으로 이루어져 있으며, 각 질문에 1점 부터 5점 까지의 범위로 완전 동의하면 5점, 그 반대는 1점을 나타낸다. 질문들은 빅 파이브 성격테스트에서 분류한 각 5가지의 성향을 확인 할 수 있는 질문으로 이루어져 있다. 결과적으로 설문지에 대한 답변의 총 합을 통해 성격을 파악 할 수 있다. 다섯가지의 성향은 신경성(N; Neuroticism), 외향성(E; Extraversion), 개방성(O; Openness to Experience), 우호성(A; Agreeableness), 성실성(C; Conscientiousness)으로 분류된다.
2. Data
다음의 내용은 데이터의 출처와 간략한 설명을 포함하고 있다.
COVID-19
위의 데이터는 WHO Coronavirus Disease (COVID-19) Dashboard에서 최신의 코로나바이러스 데이터를 얻기 위해 사용하였다.
ISO 3166-2: ISO 3166-2 code. Formatted as: ISO 3166-2:[2 characters]
총 3개의 데이터를 병합하여 최종적으로 원하는 데이터 세트를 완성하는것을 목표로 하였고, 최종 데이터 세트와 함께 분석을 하였다. 그럼 그 최종 데이터 세트를 얻기 위한 과정을 함께 보자.
3. 데이터 처리
데이터 전처리를 시작하기에 앞서, 가장 먼저 해야 할 것은 데이터를 불러오는것이다. 데이터를 불러오기 위해 다양한 방법들이 있지만, 각 데이터를 포함하고 있는 웹 사이트에서 다운을 받아 로컬에 저장 후 사용하였다.
#Library
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from scipy.stats import pearsonr, spearmanr
전 세계 국가를 대상으로, 일별로 코로나 바이러스 확진자, 누적 확진자, 코로나 바이러스로 인한 사망자, 누적 사망자를 확인 할 수 있다. 제일 첫번째 행을 보면 2020년 1월 3일 아프가니스탄에서는 확진자, 누적 확진자, 사망자, 누적 사망자가 모두 0명을 알 수 있다.
다음은 현재를 기준으로 가장 많은 누적 확진자수를 보여주는 4개의 국가의 일별 트렌드를 보여준다.
위의 그래프 처럼 국가별로 날짜, 일을 기준으로 확진자수를 확인 할 수 있었다.
데이터 전처리를 진행 하였을 때, WHO에서 제공하는 코로나 바이러스 데이터의 Header가 공백을 포함하고 있는 것을 확인 하였다. 따라서, 제일 먼저 strip()이라는 메서드를 사용하여, 공백을 제거 하였다.
# 열의 이름 공백 제거
cols = corona_df.columns.to_list()
corona_df.columns = [element.strip() for element in cols]
분석의 목표는 국가 성향별, 확진자수의 많고 적음을 확인하고 싶은 것이기 때문에, 국가별 총 확진자수가 필요하다. 그래서, 위의 데이터 세트에서 New_cases를 활용하여 국가별로 groupby하여 총합을 구하는 방식으로 활용하였다.
각 성향별로 모든 문제의 총 합을 구하기 위해서는 결측치가 없어야 한다. 데이터를 보면, NaN값은 없는데 0으로 대답한 경우를 알 수 있다.
따라서, 0점으로 대답을 한 경우 결측치 처리를 하고, 모든 결측치를 제외하자. 또, 빅 파이브 성격테스트에서 국가의 이름이 None으로 설정된 경우가 있다. 이 또한 결측치 처리를 하고, 제외하자.
# 결측치 처리
trait = trait.replace(0,np.NaN).dropna(axis = 0).reset_index(drop = True)
# 국가명이 None 인 경우 삭제
i = trait.loc[trait.country == 'NONE'].index
trait.drop(i, inplace= True)
답이 0인 경우 결측치로 분류, 국가이름이 None인 경우 결측치 처리.
여기서 중요한 가정이 설립된다. 먼저, 국민들의 성향으로 국가를 대표하기 위해서는 충분한 샘플 사이즈가 필요하다. 그렇지 않게 되면, 극단적으로 국민 1명이 국가를 대표하게 되면서 엄청나게 편향된 정보를 주기 때문이다. 따라서, 충분한 샘플 사이즈로 1000명으로 가정을 하여서, train data로서 나중에 분류를 학습하기 위한 데이터로 설정하였다.
# 데이터의 크기가 충분한 국가만 추출
train_countries = pd.DataFrame(data = trait.groupby('country')\
.agg('size')\
.loc[trait.groupby('country').agg('size') > 1000])
train_countries = train_countries.index.to_list()
나중에 K-means clustering을 Training을 하기위한 데이터를 만들기 위해 샘플 사이즈가 충분해 그 나라를 대표할 수 있는경우
추가적으로, 몇 개의 국가들은 990개 980개등 수치적으로 1000개의 샘플 사이즈와 근접한 국가들이 존재하였다. 그 국가들은, 모델의 성능 또는 결과를 테스트하기 위해서 test data로 정의 하였다. 먼저 1000개의 샘플 사이즈는 넘지 않는 국가들로 데이터를 구성하여, 그 중에서 500개의 이상의 샘플 사이즈를 가지도록 test data를 정의하였다.
# train 데이터와 test 데이터
train = trait.loc[trait.country.isin(filtered_countries)].reset_index()
test = trait.loc[~trait.country.isin(filtered_countries)].reset_index(drop = True)
# test 데이터 또한 샘플이 최소 500개는 가지도록
test_countries = test.groupby('country').size()\
.loc[test.groupby('country').size() > 500]\
.index.to_list()
test = test.loc[test.country.isin(test_countries)]
test 할 나라들도 최소 500개의 샘플 데이터는 가지도록 분류
합계를 내어, 평균을 계산하기 위해서는 점수 스케일 작업이 필요하다. 예를 들어, 외향성을 확인하는 첫번째 질문이 파티를 좋아합니까?일 경우, 5점은 굉장한 외향성을 나타낸다고 볼 수 있는 반면에, 외향성을 확인하는 두번째 질문은 나는 말을 많이 하는편이 아니다.이다. 이 질문에서 5점은 외향성의 반대의 성향을 크게 나타낸다. 따라서, 앞에서 정의 했던바와 같이 긍정적인 질문과 부정적인 질문을 나누어서, 부정적인 질문들의 점수6을 빼주어서 위의 나는 말을 많이 하는편이 아니다에서 1점이 될 수 있도록 점수 스케일을 통일 시켜주었다.
# 평균 계산을 위해 negative question 점수 scale 바꾸기
train[neg_questions] = train[neg_questions].apply(lambda x: 6 - x)
test[neg_questions] = test[neg_questions].apply(lambda x: 6 - x)
부정적인 질문들의 점수 Scale을 바꿈
# 설문지 결과 Table
df_train = train.copy()
df_test = test.copy()
결측치도 제거하였고, 점수 스케일링도 통일 시켜주었기 때문에, 합한 다음 평균을 내보자. 먼저 같은 성향을 가진 점수들끼리 합하는 코드를 list comprehension을 통해서 만들었다. 그런다음 열 합산을 통하여 합산 하였다.
같은 성향을 파악하는 질문의 합을 구하는 함수
def summing_axis (df):
traits = ['OPN','CSN','EXT','AGR','EST']
for trait in traits:
df[trait] = df[[col for col in df.columns if trait in col]].sum(axis = 1)
return df[traits+['country']]
마지막으로, `groupby`를 통해 국가별로, `mean`을 통해 평균을 구한 다음 편의를 위해 header 또한 다 바꾸어 주었다.
```py
# 나라별로 train data mean 구하기
mean_train = df_train.groupby('country').mean().rename_axis('Code').reset_index()
mean_train.columns = ['국가코드', '개방성', '성실성', '외향성', '우호성', '안정성']
국가코드
개방성
성실성
외향성
우호성
안정성
AE
37.639791
34.032090
30.261933
37.917770
31.475732
AR
40.133075
31.678530
28.345068
36.416248
32.381431
AT
40.836251
32.518538
29.899588
36.876931
29.856334
AU
38.551472
33.626061
29.937915
37.918328
30.393272
BE
39.308450
32.029262
29.967453
37.661989
30.598089
test data 또한 같은 방법으로 적용한 결과는 다음과 같다.
# 나라별로 test data mean 구하기
mean_test = df_test.groupby('country').mean().rename_axis('Code').reset_index()
mean_test.columns = ['국가코드', '개방성', '성실성', '외향성', '우호성', '안정성']
국가코드
개방성
성실성
외향성
우호성
안정성
CR
39.633028
32.664220
28.759633
35.908257
31.051376
EC
38.383138
31.910352
29.119530
35.337247
31.806830
EE
38.964045
32.362921
28.283146
35.783146
30.279775
EG
37.943890
33.007481
28.480050
36.966334
33.011222
IS
39.057728
32.614525
30.225326
37.696462
30.463687
3.3 데이터 병합
앞에서 코로나바이러스 데이터를 통한 총 확진자수를 빅 파이브 성격테스트의 결과와 국가코드를 통하여 병합 해주었다.
# train 데이터 필터링
train_covid = df_covid.loc[df_covid['국가코드'].isin(train_countries)].reset_index(drop = True)
# 빅 파이브 성격테스트와 COVID19 데이터 합치기
df_train = train_covid.merge(mean_train, on = '국가코드')
국가
국가코드
확진자 수
개방성
성실성
외향성
우호성
안정성
Argentina
AR
798486
40.133075
31.678530
28.345068
36.416248
32.381431
Australia
AU
27149
38.551472
33.626061
29.937915
37.918328
30.393272
Austria
AT
49886
40.836251
32.518538
29.899588
36.876931
29.856334
Belgium
BE
132109
39.308450
32.029262
29.967453
37.661989
30.598089
Brazil
BR
4915289
40.536946
31.240467
26.505017
34.946725
31.545703
국가별 성향 + 총 확진자수를 포함한 최종 데이터 세트를 만들어 볼 수 있었다. 이제 완성된 train data를 통하여, K-means clustering 모델을 학습 시킨 후, 그를 바탕으로 test data를 적용하여 그 결과도 같이 확인 해보도록 하자.
3.4 Clustering
K-means clustering 모델을 설정하기 위해서, hyper parameter인 k를 미리 설정해야 한다. k를 설정하기 위해서 2가지 방법을 사용하였다. 먼저 elbow plot을 통해서, 적절한 k를 확인하여 범위를 좁혔다. 범위를 좁힌 k의 값들로 모델에 적용하여, 클러스터링 결과를 확인해 보고 각 클러스터별 분포가 고르게 되었는지도 확인하여 최종 k를 결정하였다. 이 모든 과정의 결과로 k는 2로 설정하였다.
# elbow plot
distortions = []
K = range(1,10)
for k in K:
kmeanModel = KMeans(n_clusters=k)
kmeanModel.fit(df_train.iloc[:,3:8])
distortions.append(kmeanModel.inertia_)
plt.figure(figsize=(16,8))
plt.plot(K, distortions, 'bx-')
plt.xlabel('k')
plt.ylabel('Distance')
plt.title('The Elbow Plot')
plt.vlines(x=3, ymin=0, ymax=300, alpha=0.5, color='blue', linestyle='dashed', linewidth=1.0)
plt.show()
팔꿈치 처럼 꺾이는 곳은 k=3 이다. 하지만, clustering 결과 후 분포도 중요하다.
# k에 따른 분포 비교
for k in range(2,5):
kmeanModel = KMeans(n_clusters=k)
kmeanModel.fit(df_train.iloc[:,3:8])
dftrain['군집'] = kmeanModel.labels
print('k = ', k)
print(df_train['군집'].value_counts(),'\n')
k = 2
0 26
1 24
Name: 군집, dtype: int64
k = 3
1 22
2 16
0 12
Name: 군집, dtype: int64
k = 4
0 22
2 13
1 9
3 6
Name: 군집, dtype: int64
> 가장 고르게 분포된, k=2 설정
```py
#k = 2로 설정
kmeans = KMeans(n_clusters=2)
kmeans.fit(df_train.iloc[:,3:8])
df_train['군집'] = kmeans.labels_
국가
국가코드
확진자 수
개방성
성실성
외향성
우호성
안정성
군집
Argentina
AR
798486
40.133075
31.678530
28.345068
36.416248
32.381431
1
Australia
AU
27149
38.551472
33.626061
29.937915
37.918328
30.393272
0
Austria
AT
49886
40.836251
32.518538
29.899588
36.876931
29.856334
0
Belgium
BE
132109
39.308450
32.029262
29.967453
37.661989
30.598089
0
Brazil
BR
4915289
40.536946
31.240467
26.505017
34.946725
31.545703
1
여기서 미국과 인도의 확진자수는 다른 국가들에 비해, 상대적으로 엄청나게 많은 확진자수를 보유하기 때문에 좀 더 일반적인 결과를 도출 하기위해서, 둘 국가는 oulier로 제외하였다.
# 인도와 미국의 확진자수를 Outlier 취급
i = df_train.loc[(df_train['국가'] == 'India') | (df_train['국가'] == 'United States of America')].index
df_train.drop(i, inplace=True)
최종적으로, 클러스터링의 결과로 groupby한 다음, mean을 취해주어서, 클러스터 별 평균 확진자수와 평균 성향을 알아 볼 수 있는 최종결과를 확인 할 수 있었다.
train data와 test data의 결과를 비교해보니, 꽤나 좋은 성능을 확인 할 수 있었다. 먼저 확진자수가 군집 1에서 평균적으로 높음을 알 수 있었다. 그리고 군집 1의 성향은 개방성이 군집 0보다 약 1점가량 높게 나왔음을 알 수 있다. 반면에 우호성은 군집 0에 비해 상대적으로 낮음을 알 수 있었다. 개방성은 간단히 설명하면, 야외 엑티비티를 좋아하는 성향으로 볼 수 있는데 그 결과로 군집 1의 확진자수가 높음을 예상할 수 있었다. 반면에 개방성도 높지만 우호성이 높은 군집 0의 경우 좀 더 주어진 환경에 잘 적응함을 나타내는데, 비록 야외 활동을 좋아하지만 코로나 바이러스로 바뀐 문화에 적응하여 다른 방식으로 야외 활동을 즐겼기 때문에 평균 확진자수가 군집 1에 비해 낮은것이 아닐까 추측할 수 있다.
4. 결과
위의 그래프를 통해서, Test data와 Train data의 클러스터링 결과를 확인할 수 있었다. 예상대로, Cluster 0의 확진자 수가 Cluster 1의 확진자 수보다 많음을 확인 할 수 있었고, 가장 놀라운 사실은 두 데이터 모두 Cluster 0의 확진자 수가 Cluster 1의 확진자 수의 비율이 되게 비슷하다는 것이다. 물론, 이 결과를 통해서 코로나 확산의 요인 중의 하나는 빅 파이브 성격테스트 이다라고 말 할 순 없다. 이 모든 결과들 또한 운이 좋아 그렇게 나온 것일 수 있다. 하지만, 그래도 이 프로젝트를 통해서 나라의 성향을 파악할 수 있고, 코로나바이러스의 확산의 요인중에 하나 일 수 있지 않을까 라는 생각과 직접적인 요소는 아니더라도 간접적인 요인이 될 수 있지 않을까 생각한다.
1. Research Question
잠깐 잠잠했던 확산을 뒤로하고, 다시금 COVID-19의 확산이 활발히 진행되고 있음에 따라, 전 세계가 코로나바이러스 확산을 최소화 하기 위해 최선을 다하고 있다. 확산을 최소화 하기 위해서는 정확한 요인을 파악하여 대처해야 한다. 캐글(Kaggle)에서 COVID19 Global Forecasting (Week 1) 같은 Challenge를 발표한 사례도 있다. 내가 주목한 부분은 국가별로 확진자수가 다르다는 점이다. 물론 국가별로 다를 수 있는 요소들에 다양할 수가 있지만, 예를 들어 국가별 대응 정책, 국민의 성향, 정부와의 신뢰관계 등이 있다. 내가 선택한 요인으로는 국가별 성향이 코로나바이러스 확산과 관계가 있을 수 있다고 생각했다. 따라서, K-means clustering을 활용하여 비슷한 성향을 가진 국가들의 코로나 확진자수의 관계를 확인해보자.
1.1 Big Five Personality Test
국가별 성향을 확인하기위해서 캐글에 있는 빅 파이브 성격테스트를 사용하였다. 한국을 예를 들면, 다음과 같다. 캐글에 빅 파이브 성격테스트에서 한국인 국적을 가진 사람들의 데이터를 모아서, 평균을 내어 한국의 성향으로 분석을 하였다. 빅 파이브 성격테스트에 대해서 간단히 알아보면, 기본적으로 설문지에 대답하는 형식으로 이루어져 있으며, 각 질문에 1점 부터 5점 까지의 범위로 완전 동의하면 5점, 그 반대는 1점을 나타낸다. 질문들은 빅 파이브 성격테스트에서 분류한 각 5가지의 성향을 확인 할 수 있는 질문으로 이루어져 있다. 결과적으로 설문지에 대한 답변의 총 합을 통해 성격을 파악 할 수 있다. 다섯가지의 성향은 신경성(N; Neuroticism), 외향성(E; Extraversion), 개방성(O; Openness to Experience), 우호성(A; Agreeableness), 성실성(C; Conscientiousness)으로 분류된다.
2. Data
다음의 내용은 데이터의 출처와 간략한 설명을 포함하고 있다.
총 3개의 데이터를 병합하여 최종적으로 원하는 데이터 세트를 완성하는것을 목표로 하였고, 최종 데이터 세트와 함께 분석을 하였다. 그럼 그 최종 데이터 세트를 얻기 위한 과정을 함께 보자.
3. 데이터 처리
데이터 전처리를 시작하기에 앞서, 가장 먼저 해야 할 것은 데이터를 불러오는것이다. 데이터를 불러오기 위해 다양한 방법들이 있지만, 각 데이터를 포함하고 있는 웹 사이트에서 다운을 받아 로컬에 저장 후 사용하였다.
3.1 코로나바이러스 데이터를 통해 총 확진자수 구하기
WHO에서 제공하는 코로나 바이러스 데이터프레임을 같이 한 번 살펴보자.
전 세계 국가를 대상으로, 일별로 코로나 바이러스 확진자, 누적 확진자, 코로나 바이러스로 인한 사망자, 누적 사망자를 확인 할 수 있다. 제일 첫번째 행을 보면 2020년 1월 3일 아프가니스탄에서는 확진자, 누적 확진자, 사망자, 누적 사망자가 모두 0명을 알 수 있다.
다음은 현재를 기준으로 가장 많은 누적 확진자수를 보여주는 4개의 국가의 일별 트렌드를 보여준다.
데이터 전처리를 진행 하였을 때, WHO에서 제공하는 코로나 바이러스 데이터의 Header가 공백을 포함하고 있는 것을 확인 하였다. 따라서, 제일 먼저
strip()
이라는 메서드를 사용하여, 공백을 제거 하였다.분석의 목표는 국가 성향별, 확진자수의 많고 적음을 확인하고 싶은 것이기 때문에, 국가별 총 확진자수가 필요하다. 그래서, 위의 데이터 세트에서 New_cases를 활용하여 국가별로
groupby
하여 총합을 구하는 방식으로 활용하였다.마지막으로, Header의 이름을 보기 편하게 바꾸어 주었다.
3.2 빅 파이브 성격테스트 결과
빅 파이브 성격테스트의 데이터의 전처리를 시작해보자. 먼저 raw data의 생김새를 확인해보자.
위의 데이터 프레임을 보는것과 같이 각 Header가 성향 + 질문 Number로 구성되어 있다. 예를 들어, EXT1은 외향성을 확인하는 첫번째 질문인 것이다. 그리고, 답변자의 국적을 확인할 수 있었다. 따라서 다음과 같은 전처리 과정을 생각 할 수 있다.
각 성향을 확인하는 질문의 총합을 구한다.
국가별로
groupby
하여 평균을 낸다.그럼 시작해보자.
각 성향별로 모든 문제의 총 합을 구하기 위해서는 결측치가 없어야 한다. 데이터를 보면, NaN값은 없는데 0으로 대답한 경우를 알 수 있다. 따라서, 0점으로 대답을 한 경우 결측치 처리를 하고, 모든 결측치를 제외하자. 또, 빅 파이브 성격테스트에서 국가의 이름이 None으로 설정된 경우가 있다. 이 또한 결측치 처리를 하고, 제외하자.
여기서 중요한 가정이 설립된다. 먼저, 국민들의 성향으로 국가를 대표하기 위해서는 충분한 샘플 사이즈가 필요하다. 그렇지 않게 되면, 극단적으로 국민 1명이 국가를 대표하게 되면서 엄청나게 편향된 정보를 주기 때문이다. 따라서, 충분한 샘플 사이즈로 1000명으로 가정을 하여서, train data로서 나중에 분류를 학습하기 위한 데이터로 설정하였다.
추가적으로, 몇 개의 국가들은 990개 980개등 수치적으로 1000개의 샘플 사이즈와 근접한 국가들이 존재하였다. 그 국가들은, 모델의 성능 또는 결과를 테스트하기 위해서 test data로 정의 하였다. 먼저 1000개의 샘플 사이즈는 넘지 않는 국가들로 데이터를 구성하여, 그 중에서 500개의 이상의 샘플 사이즈를 가지도록 test data를 정의하였다.
합계를 내어, 평균을 계산하기 위해서는 점수 스케일 작업이 필요하다. 예를 들어, 외향성을 확인하는 첫번째 질문이 파티를 좋아합니까?일 경우, 5점은 굉장한 외향성을 나타낸다고 볼 수 있는 반면에, 외향성을 확인하는 두번째 질문은 나는 말을 많이 하는편이 아니다.이다. 이 질문에서 5점은 외향성의 반대의 성향을 크게 나타낸다. 따라서, 앞에서 정의 했던바와 같이 긍정적인 질문과 부정적인 질문을 나누어서, 부정적인 질문들의 점수6을 빼주어서 위의 나는 말을 많이 하는편이 아니다에서 1점이 될 수 있도록 점수 스케일을 통일 시켜주었다.
결측치도 제거하였고, 점수 스케일링도 통일 시켜주었기 때문에, 합한 다음 평균을 내보자. 먼저 같은 성향을 가진 점수들끼리 합하는 코드를 list comprehension을 통해서 만들었다. 그런다음 열 합산을 통하여 합산 하였다.
같은 성향을 파악하는 질문의 합을 구하는 함수
def summing_axis (df): traits = ['OPN','CSN','EXT','AGR','EST'] for trait in traits: df[trait] = df[[col for col in df.columns if trait in col]].sum(axis = 1) return df[traits+['country']]
df_train = summing_axis(df_train) df_test = summing_axis(df_test)
test data 또한 같은 방법으로 적용한 결과는 다음과 같다.
3.3 데이터 병합
앞에서 코로나바이러스 데이터를 통한 총 확진자수를 빅 파이브 성격테스트의 결과와 국가코드를 통하여 병합 해주었다.
국가별 성향 + 총 확진자수를 포함한 최종 데이터 세트를 만들어 볼 수 있었다. 이제 완성된 train data를 통하여, K-means clustering 모델을 학습 시킨 후, 그를 바탕으로 test data를 적용하여 그 결과도 같이 확인 해보도록 하자.
3.4 Clustering
K-means clustering 모델을 설정하기 위해서, hyper parameter인 k를 미리 설정해야 한다. k를 설정하기 위해서 2가지 방법을 사용하였다. 먼저 elbow plot을 통해서, 적절한 k를 확인하여 범위를 좁혔다. 범위를 좁힌 k의 값들로 모델에 적용하여, 클러스터링 결과를 확인해 보고 각 클러스터별 분포가 고르게 되었는지도 확인하여 최종 k를 결정하였다. 이 모든 과정의 결과로 k는 2로 설정하였다.
for k in range(2,5): kmeanModel = KMeans(n_clusters=k) kmeanModel.fit(df_train.iloc[:,3:8]) dftrain['군집'] = kmeanModel.labels print('k = ', k) print(df_train['군집'].value_counts(),'\n')
여기서 미국과 인도의 확진자수는 다른 국가들에 비해, 상대적으로 엄청나게 많은 확진자수를 보유하기 때문에 좀 더 일반적인 결과를 도출 하기위해서, 둘 국가는 oulier로 제외하였다.
최종적으로, 클러스터링의 결과로
groupby
한 다음,mean
을 취해주어서, 클러스터 별 평균 확진자수와 평균 성향을 알아 볼 수 있는 최종결과를 확인 할 수 있었다.train data를 통해서 학습 되어진 모델에 test data를 적용시켜 보았다. train data와 같은 방법으로 최종결과를 확인 할 수 있었다.
3.5 Test
train data와 test data의 결과를 비교해보니, 꽤나 좋은 성능을 확인 할 수 있었다. 먼저 확진자수가 군집 1에서 평균적으로 높음을 알 수 있었다. 그리고 군집 1의 성향은 개방성이 군집 0보다 약 1점가량 높게 나왔음을 알 수 있다. 반면에 우호성은 군집 0에 비해 상대적으로 낮음을 알 수 있었다. 개방성은 간단히 설명하면, 야외 엑티비티를 좋아하는 성향으로 볼 수 있는데 그 결과로 군집 1의 확진자수가 높음을 예상할 수 있었다. 반면에 개방성도 높지만 우호성이 높은 군집 0의 경우 좀 더 주어진 환경에 잘 적응함을 나타내는데, 비록 야외 활동을 좋아하지만 코로나 바이러스로 바뀐 문화에 적응하여 다른 방식으로 야외 활동을 즐겼기 때문에 평균 확진자수가 군집 1에 비해 낮은것이 아닐까 추측할 수 있다.
4. 결과
위의 그래프를 통해서, Test data와 Train data의 클러스터링 결과를 확인할 수 있었다. 예상대로, Cluster 0의 확진자 수가 Cluster 1의 확진자 수보다 많음을 확인 할 수 있었고, 가장 놀라운 사실은 두 데이터 모두 Cluster 0의 확진자 수가 Cluster 1의 확진자 수의 비율이 되게 비슷하다는 것이다. 물론, 이 결과를 통해서 코로나 확산의 요인 중의 하나는 빅 파이브 성격테스트 이다라고 말 할 순 없다. 이 모든 결과들 또한 운이 좋아 그렇게 나온 것일 수 있다. 하지만, 그래도 이 프로젝트를 통해서 나라의 성향을 파악할 수 있고, 코로나바이러스의 확산의 요인중에 하나 일 수 있지 않을까 라는 생각과 직접적인 요소는 아니더라도 간접적인 요인이 될 수 있지 않을까 생각한다.
Full_Code_Notebook