본문 바로가기
AI/ML

[Kaggle] Depression Dataset - 상관 관계 분석

by 문찬웅 2024. 11. 30.

들어가며

이번 게시물에서는 Machine Learning의 분석 방법에 익숙해지기 위해 Kaggle의 데이터셋 중 Depression Dataset을 분석한 과정에 대해 정리했습니다.

Kaggle Depression Dataset : https://www.kaggle.com/datasets/anthonytherrien/depression-dataset

 

Depression Dataset

A Comprehensive Dataset for Analyzing Health, Lifestyle, and Socio-Economic Fact

www.kaggle.com


Depression Dataset(우울증 데이터셋)

이 데이터 세트에는 개인 및 생활 방식 요소와 관련된 다양한 속성을 가진 개인에 대한 정보가 포함되어 있습니다. 이는 건강, 생활방식, 사회경제적 지위 등의 영역에 대한 분석을 용이하게 하도록 설계되었습니다.

특성

수치형 데이터

  • 나이(Age): 개인의 나이입니다.
  • 자녀 수(Number of Children): 개인이 가진 자녀 수입니다.
  • 소득(Income): 개인의 연간 소득(USD).

범주형 데이터

  • 결혼 상태(Marital Status): 개인의 결혼 상태입니다. 가능한 값은 미혼, 기혼, 이혼, 과부입니다.
  • 교육 수준(Education Level): 개인이 달성한 최고 교육 수준입니다. 가능한 값은 고등학교, 준학사 학위, 학사 학위, 석사 학위, 박사입니다.
  • 흡연 상태(Smoking Status): 개인이 흡연자인지 여부를 나타냅니다. 가능한 값은 흡연자,
    이전, 비흡연자입니다.
  • 신체 활동 수준(Physical Activity Level): 개인이 수행한 신체 활동 수준입니다. 가능한 값은 좌식, 중간, 활동적입니다.
  • 고용 상태(Employment Status): 개인의 고용 상태입니다. 가능한 값으로는 취업 및 실업이 있습니다.
  • 알코올 소비(Alcohol Consumption): 알코올 소비 수준. 가능한 값으로는 낮음, 보통, 높음이 있습니다.
  • 식습관(Dietary Habits): 개인의 식습관. 가능한 값으로는 건강, 보통, 건강에 해로움이 있습니다.
  • 수면 패턴(Sleep Patterns): 수면의 질. 가능한 값으로는 좋음, 보통, 나쁨이 있습니다.
  • 정신 질환 병력(History of Mental Illness): 개인에게 정신 질환 병력이 있는지 여부입니다. 가능한 값으로는 예와 아니요가 있습니다.
  • 약물 남용 병력(History of Substance Abuse): 개인에게 약물 남용 병력이 있는지 여부입니다. 가능한 값으로는 예와 아니요가 있습니다.
  • 우울증 가족 병력(Family History of Depression): 우울증 가족 병력이 있는지 여부를 나타냅니다. 가능한 값으로는 예와 아니요가 있습니다.
  • 만성 질환(Chronic Medical Conditions): 개인에게 만성 질환이 있는지 여부입니다. 가능한 값은 예와 아니요입니다.

기타

  • 이름(Name): 개인의 전체 이름입니다.(이 경우 특성이 될 수 없습니다)

사용

이 데이터 세트는 다양한 건강, 라이프스타일 및 사회 경제적 요인을 분석하는 데 사용하도록 의도되었습니다. 예측 모델링, 클러스터링 및 탐색적 데이터 분석과 같은 작업에 적합합니다.

데이터셋 다운로드

kagglehub 패키지의 dataset_download() 함수를 이용해 데이터셋을 다운로드하고 pandas의 read_csv() 함수로 dataframe을 읽어옵니다.

import kagglehub
import pandas as pd

# Download latest version
path = kagglehub.dataset_download("anthonytherrien/depression-dataset")

print("Path to dataset files:", path)

df = pd.read_csv(path + "/depression_data.csv")

# DataSet 특징 확인
df.info()

# DataSet 요약 통계
df.describe()

# DataSet 결측값 확인(결측값이 없는 것을 확인할 수 있음)
df.isnull().sum()

df.info() 의 결과값

'''
df.info() 의 결과값

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 413768 entries, 0 to 413767
Data columns (total 15 columns):
 #   Column                        Non-Null Count   Dtype  
---  ------                        --------------   -----  
 0   Age                           413768 non-null  int64  
 1   Marital Status                413768 non-null  object 
 2   Education Level               413768 non-null  object 
 3   Number of Children            413768 non-null  int64  
 4   Smoking Status                413768 non-null  object 
 5   Physical Activity Level       413768 non-null  object 
 6   Employment Status             413768 non-null  object 
 7   Income                        413768 non-null  float64
 8   Alcohol Consumption           413768 non-null  object 
 9   Dietary Habits                413768 non-null  object 
 10  Sleep Patterns                413768 non-null  object 
 11  History of Mental Illness     413768 non-null  object 
 12  History of Substance Abuse    413768 non-null  object 
 13  Family History of Depression  413768 non-null  object 
 14  Chronic Medical Conditions    413768 non-null  object 
dtypes: float64(1), int64(2), object(12)
memory usage: 47.4+ MB
'''

수치형 데이터셋의 요약 통계(개수, 평균, 표준편차 등)

df.descibe()의 결과값

Dataset 결측값 확인

df.isnull().sum()

데이터셋 전처리

의미 없는 데이터 제거

# 의미를 찾을 수 없는 데이터인 'Name' 속성 제거
df.drop(labels='Name', axis=1, inplace=True)

Ordinal Encoding

순서를 유지하며 수치화 할 수 있는 데이터는 다음과 같다.(Label Encoding, Ordinal Encoding)

  • 교육 수준(Education Level): 개인이 달성한 최고 교육 수준입니다. 가능한 값은 고등학교, 준학사 학위, 학사 학위, 석사 학위, 박사입니다.
  • 신체 활동 수준(Physical Activity Level): 개인이 수행한 신체 활동 수준입니다. 가능한 값은 좌식, 중간, 활동적입니다.
  • 알코올 소비(Alcohol Consumption): 알코올 소비 수준. 가능한 값으로는 낮음, 보통, 높음이 있습니다.
  • 식습관(Dietary Habits): 개인의 식습관. 가능한 값으로는 건강, 보통, 건강에 해로움이 있습니다.
  • 수면 패턴(Sleep Patterns): 수면의 질. 가능한 값으로는 좋음, 보통, 나쁨이 있습니다.

Binary Encoding

0과 1으로 나타낼 수 있는 Binary Encoding 을 적용할 수 있는 데이터는 다음과 같다.

  • 정신 질환 병력(History of Mental Illness): 개인에게 정신 질환 병력이 있는지 여부입니다. 가능한 값으로는 예와 아니요가 있습니다.
  • 약물 남용 병력(History of Substance Abuse): 개인에게 약물 남용 병력이 있는지 여부입니다. 가능한 값으로는 예와 아니요가 있습니다.
  • 우울증 가족 병력(Family History of Depression): 우울증 가족 병력이 있는지 여부를 나타냅니다. 가능한 값으로는 예와 아니요가 있습니다.
  • 만성 질환(Chronic Medical Conditions): 개인에게 만성 질환이 있는지 여부입니다. 가능한 값은 예와 아니요입니다.
from sklearn.preprocessing import OrdinalEncoder

ordinal_categories = {
    # Ordinal Encoder 순서 지정
    'Education Level': ["High School", "Associate Degree", "Bachelor's Degree", "Master's Degree", "PhD"],
    'Physical Activity Level': ['Sedentary', 'Moderate', 'Active'],
    'Alcohol Consumption': ['Low', 'Moderate', 'High'],
    'Dietary Habits': ['Unhealthy', 'Moderate', 'Healthy'],
    'Sleep Patterns': ['Poor', 'Fair', 'Good'],

    # Binary Encoder 도 함께 지정(순서에 따라 0, 1 이 됨)
    'History of Mental Illness': ['No', 'Yes'],
    'History of Substance Abuse': ['No', 'Yes'],
    'Family History of Depression': ['No', 'Yes'],
    'Chronic Medical Conditions': ['No', 'Yes'],
}

for column, categories in ordinal_categories.items():
    ordinal_encoder = OrdinalEncoder(categories=[categories])
    df.loc[:, column] = ordinal_encoder.fit_transform(df[[column]])

One-Hot Encoding

순서가 없는 범주형 변수로서 각 특성값에 대한 Column을 추가하여 0과 1로 나타내는 One-Hot Encoding 을 적용할 수 있는 데이터는 다음과 같다.

  • 결혼 상태(Marital Status): 개인의 결혼 상태입니다. 가능한 값은 미혼, 기혼, 이혼, 과부입니다.
  • 흡연 상태(Smoking Status): 개인이 흡연자인지 여부를 나타냅니다. 가능한 값은 흡연자,
  • 고용 상태(Employment Status): 개인의 고용 상태입니다. 가능한 값으로는 취업 및 실업이 있습니다.
import pandas as pd
from sklearn.preprocessing import OneHotEncoder

# OneHotEncoder 초기화
# - Array를 반환하도록 sparse_output 옵션을 False로 설정
# - 첫 번째 카테고리 제외
one_hot_encoder = OneHotEncoder(sparse_output=False, drop='first')

categorical_columns = ['Marital Status', 'Smoking Status', 'Employment Status']

encoded_features = one_hot_encoder.fit_transform(df[categorical_columns])
encoded_feature_names = one_hot_encoder.get_feature_names_out(categorical_columns)

df.loc[:, encoded_feature_names] = pd.DataFrame(
    encoded_features,
    columns=encoded_feature_names
)

df.drop(columns=categorical_columns, inplace=True)
인코딩이 완료된 데이터는 다음과 같은 형태로 나타납니다.(표로 넣고 싶었는데 블로그 레이아웃이 잘 맞지 않음)

[수치형 데이터]
Age: 31
Income: 26265.67
Number of Children: 2 

[Ordinal Encoding]
Education Level: 2.0 (Bachelor's Degree)
Physical Activity Level: 2.0 (Active)
Alcohol Consumption: 1.0
Dietary Habits: 1.0
Sleep Patterns: 1.0

[Binary Encoding]
History of Mental Illness: 1.0
History of Substance Abuse: 0.0
Family History of Depression: 1.0
Chronic Medical Conditions: 1.0

[One-Hot Encoding]
Marital Status_Married: 1.0 (Married)
Marital Status_Single: 0.0
Marital Status_Widowed: 0.0
Smoking Status_Former: 0.0
Smoking Status_Non-smoker: 1.0 (Non-smoker)
Employment Status_Unemployed: 1.0 (Unemployed)


수치형 데이터 시각화 및 상관관계 분석(seaborn)

Python 의 seaborn 라이브러리를 이용해 인코딩 된 데이터셋의 상관관계를 분석해보겠습니다.

import matplotlib.pyplot as plt
import seaborn as sns

# 수치형 변수 분석
numeric_cols = ['Age', 'Number of Children', 'Income']

plt.figure(figsize=(15, 5))
for i, col in enumerate(numeric_cols, 1):
    plt.subplot(1, 3, i)
    sns.histplot(data=df, x=col, kde=True) # 치수 그래프 표시
    plt.title(f'Distribution of {col}')
plt.tight_layout()
plt.show()

# 상관관계 분석
plt.figure(figsize=(12, 8))
sns.heatmap(df.corr(), annot=True, cmap='coolwarm', fmt='.2f')
plt.title('Correlation Matrix')
plt.show()

수치형 데이터 시각화에 따르면 현재 데이터셋의 수치형 데이터에서 확인할 수 있는 정보는 다음과 같다.

  • 나이에 따른 환자 정보가 고르게 분포되어 있다.
  • 자녀의 수가 많을 수록 우울증의 비율이 적다.
  • 소득이 완전히 적을 때 보다 20,000$~40,000$ 사이일 때 우울증의 비율이 높다.

매트릭스에 따르면,

  • 나이와 자녀의 수
  • 나이와 사별 여부
  • 학력과 소득
  • 학력과 식습관
  • 기혼 여부와 자녀의 수
  • 미혼 여부와 신체 활동 여부
  • 식습관과 신체 활동 여부
  • 나이와 고용 여부
  • 우울증 가족 병력과 사별 여부

등이 우울증과 밀접한 상관 관계를 가지고 있는 것으로 판단해볼 수 있습니다.

우울증의 각 지표에 대한 상관관계가 아닌 인코딩 된 데이터의 높낮이에 따른 단순한 지표이므로 다른 분석 방법을 제시해야 할 것 같습니다.

마치며

오늘은 데이터를 분석에 활용하기 위해 인코딩을 적용해보았고, 비지도학습의 개념을 조금 더 명확히 한 뒤 더 유의미한 데이터를 도출할 수 있도록 공부하는 것이 좋을 것 같습니다.

읽어주셔서 감사합니다. 좋은 하루 되세요!