AI 개발 공부 공간

AI, 머신러닝, 딥러닝, Python & PyTorch, 실전 프로젝트

머신러닝/머신러닝: 실전 프로젝트 학습

인구 소득 예측 프로젝트 1 : 데이터 분석

qordnswnd123 2024. 12. 30. 14:59

1. 데이터 로드 및 확인

import pandas as pd

train = pd.read_csv('train.csv')
test = pd.read_csv('test.csv')
submission = pd.read_csv('sample_submission.csv')

display(train.head(5))
display(test.head(5))
display(submission.head(5))

 


2. 데이터 정보 확인

train.info()

 


3. 수치형(numerical) 데이터 기술통계량 확인

import matplotlib.pyplot as plt
import seaborn as sns

description = train.describe().T

fig, axs = plt.subplots(figsize=(11, 3))
sns.heatmap(description, annot=True, fmt=".2f", cmap='coolwarm', linewidths=.5, ax=axs)
axs.set_title('Descriptive Statistics Heatmap')
plt.show()

 

※ 결과 해석

각 피처(feature)의 count 값이 모두 4440으로 동일하므로 수치형 피처에 결측치는 없는 것으로 보입니다.

fnlwgt 피처는 상대적으로 큰 표준 편차를 가지고 있으며, 이는 해당 피처의 값들이 평균에서 상당히 퍼져 있음을 나타냅니다.
또한 fnlwgt와 capital.gain 피처는 최댓값이 큰 편이므로, 이상치가 존재할 가능성이 있습니다.

hours.per.week 피처의 최솟값이 1로 나타나는데, 이는 이상치의 존재 가능성을 시사합니다.

마지막으로 target 피처는 대부분 값이 0으로 나타나고, 1의 비율은 24%입니다.

이러한 결과를 고려하여 결측치 처리, 이상치 처리, 그리고 피처 스케일링과 같은 전처리 작업이 필요할 것으로 보입니다.


4. 범주형(categorical) 데이터 기술통계량 확인

train_drop = train.drop(['ID'],axis = 1)

train_drop.describe(include=['O']).T

 


5. 범주형 피처(feature) 고유값 확인

categorical_Eng = ['workclass', 'education', 'marital.status', 'occupation', 'relationship', 'race', 'sex', 'native.country']
categorical_Kor = ['근로 형태', '교육', '결혼 상태', '직업', '가족 관계', '인종', '성별', '국적']

for Eng, Kor in zip(categorical_Eng, categorical_Kor):
    unique_values = train[Eng].unique().tolist()
    print('\n {0} ({1})\n'.format(Eng, Kor), unique_values)
 workclass (근로 형태)
 ['Self-emp-not-inc', 'Private', nan, 'Local-gov', 'Self-emp-inc', 'State-gov', 'Federal-gov', 'Never-worked', 'Without-pay']

 education (교육)
 ['Some-college', 'Bachelors', 'HS-grad', '11th', 'Masters', 'Assoc-voc', '9th', '7th-8th', '10th', 'Doctorate', 'Assoc-acdm', 'Preschool', '5th-6th', '12th', 'Prof-school', '1st-4th']

 marital.status (결혼 상태)
 ['Married-spouse-absent', 'Never-married', 'Married-civ-spouse', 'Divorced', 'Separated', 'Widowed', 'Married-AF-spouse']

 occupation (직업)
 ['Craft-repair', 'Exec-managerial', 'Other-service', 'Adm-clerical', 'Farming-fishing', nan, 'Sales', 'Transport-moving', 'Prof-specialty', 'Machine-op-inspct', 'Tech-support', 'Protective-serv', 'Handlers-cleaners', 'Priv-house-serv']

 relationship (가족 관계)
 ['Not-in-family', 'Unmarried', 'Wife', 'Husband', 'Own-child', 'Other-relative']

 race (인종)
 ['White', 'Black', 'Asian-Pac-Islander', 'Amer-Indian-Eskimo', 'Other']

 sex (성별)
 ['Male', 'Female']

 native.country (국적)
 ['United-States', nan, 'Mexico', 'Guatemala', 'Puerto-Rico', 'Columbia', 'China', 'Jamaica', 'Philippines', 'Thailand', 'Portugal', 'Poland', 'Trinadad&Tobago', 'India', 'Haiti', 'Vietnam', 'Canada', 'Taiwan', 'Germany', 'Honduras', 'England', 'Dominican-Republic', 'France', 'Laos', 'El-Salvador', 'Japan', 'Ireland', 'South', 'Yugoslavia', 'Hungary', 'Peru', 'Cuba', 'Ecuador', 'Italy', 'Cambodia', 'Greece', 'Nicaragua', 'Iran', 'Outlying-US(Guam-USVI-etc)', 'Hong', 'Scotland']

 


6. 소득 수준(target)에 따른 데이터의 분포를 시각화

categories = df["target"].value_counts().index
values = df["target"].value_counts().values

plt.figure(figsize=(5,5))

pie_chart = plt.pie(x=values,
                    labels=categories,
                    autopct='%.2f%%',
                    shadow=True,
                    startangle=40,
                    wedgeprops=dict(width=0.75),
                    textprops=dict(color="white", fontsize=14, weight="bold"))

plt.legend(title="target", title_fontsize=12, loc='best', fontsize=12)
plt.title('Target Distribution', size = 15)
plt.show()

 

※ 결과 해석

여기서 target 변수는 인구의 소득 수준을 나타내며, 두 가지 카테고리 값(0 또는 1)을 가집니다.
각 카테고리 값은 소득이 특정 임계값 5만 달러를 넘는지 여부를 나타냅니다.

파이(pie) 차트에서 볼 수 있듯이, **대부분의 데이터가 하나의 클래스(소득이 5만 달러 미만인 경우, target = 0)**에 속해 있음을 알 수 있습니다.
두 번째 클래스(target = 1, 소득이 5만 달러 이상인 경우)는 전체 데이터의 작은 부분을 차지하고 있습니다.

이러한 클래스 불균형은 모델 학습에 여러 문제를 일으킬 수 있습니다.

모델의 편향성 증가: 모델은 다수 클래스에 더 많은 중점을 둘 수 있으며, 이로 인해 모델이 덜 수용적이고 다수 클래스에 편향될 수 있습니다.

오버피팅의 위험: 불균형한 데이터로 모델을 학습하면, 모델은 더 적은 샘플의 클래스에 과적합할 가능성이 있습니다.

분류 성능 저하: 모델이 소수 클래스를 제대로 학습하지 못하면, 이러한 클래스에 예측 성능이 저하될 수 있으며, 이는 전체 모델 성능의 저하로 이어질 수 있습니다.

이러한 문제를 해결하기 위해 데이터 전처리 단계에서 리샘플링 기법을 적용할 수 있습니다.
리샘플링은 클래스 불균형을 완화하며, 모델이 두 클래스를 고르게 학습할 수 있도록 도와줍니다.
리샘플링 기법에는 소수 클래스의 샘플을 증가시키는 오버샘플링(oversampling)과 다수 클래스의 샘플을 줄이는 언더샘플링(undersampling)이 포함됩니다.

또한, 모델 평가 지표를 선택할 때도 주의가 필요합니다.
불균형한 데이터에서는 정확도(accuracy)만을 사용하여 모델을 평가하는 것이 적절하지 않을 수 있으며, 정밀도(precision), 재현율(recall), F1 스코어 등 다양한 평가 지표를 고려해야 합니다.

종합적으로, 클래스 불균형 문제는 데이터 분석의 중요한 과제 사항입니다.
이를 적절하게 처리하고, 모델 학습과 평가 전략을 신중하게 선택함으로써, 더 강력하고 일반화 성능이 높은 모델을 구축할 수 있습니다.


7. 범주형 feature의 분포 시각화

categorical_columns = df.select_dtypes(include=['object']).columns

fig, axes = plt.subplots(4, 2, figsize=(13,13))
fig.suptitle('Distribution of Categorical Features')

for i, col in enumerate(categorical_columns):
    sns.countplot(y=col, data=df, ax=axes[i//2, i%2])
    axes[i//2, i%2].set_title(f'Distribution of {col}')
    axes[i//2, i%2].set_xlabel('')

plt.tight_layout(rect=[0, 0.03, 1, 0.95])
plt.show()

 

※ 결과 해석

workclass
Private: Private 클래스의 빈도가 가장 높음을 볼 수 있습니다. 이는 대부분의 사람들이 비영리 부문에서 근무하고 있음을 의미합니다.

Self-emp-not-inc 및 Self-emp-inc: 자영업자도 상당한 비율을 차지하고 있으며, 이는 사람들이 일부가 자신의 사업을 운영하고 있음을 나타냅니다.

State-gov, Local-gov, Federal-gov: 국가, 지방 및 연방 정부에서 근무하는 사람들이 있으며, 이들은 전체의 작은 부분을 차지하고 있습니다.

Without-pay 및 Never-worked: 이 두 클래스는 매우 낮은 빈도수를 가지고 있어, 이들 클래스에 속하는 사람은 매우 적다는 것을 알 수 있습니다.

 

Education
HS-grad가 가장 많은 비율을 차지하고 있으며, 이는 대부분의 인구가 최소한 고등학교 교육을 받았음을 나타냅니다.

Some-college와 Bachelors 카테고리는 상당한 비율을 차지하고 있으며, 많은 사람들이 일부 대학 교육을 받았거나 학사 학위를 취득했음을 보여줍니다.

Higher-edu(Masters)의 박사 학위(Doctorate), 전문 학위(Prof-school)를 가진 사람들은 상대적으로 작은 비율을 차지하고 있습니다.

 

Marital Status
Married-civ-spouse 카테고리가 높은 비율을 차지하고 있어, 많은 사람들이 현재 결혼해 있음을 나타냅니다.

Never-married 카테고리도 상당한 비율을 보이며, 이는 미혼인 사람들의 비율을 나타냅니다.

Divorced 카테고리는 이혼한 사람들의 비율을 보여주며, 상대적으로 더 적은 비율을 차지하고 있습니다.

 

occupation
Prof-specialty와 Craft-repair가 상당한 비율을 차지하고 있어, 전문직과 수공예 관련 직종에서 일하는 사람들이 많음을 나타냅니다.

Exec-managerial 카테고리도 높은 비율을 차지하고 있으며, 이는 경영 관련 직종에서 일하는 사람들의 비율을 나타냅니다.

나머지 직종들은 다양한 비율로 분포되어 있으며, 직종 자체는 비교적 인구가 확산하고 있다는 점을 나타냅니다.

 

Relationship
Husband 카테고리가 가장 높은 빈도를 보이며, 이는 데이터셋에 있는 개인들의 많은 수가 남편이라는 역할을 가지고 있음을 보여줍니다.

Not-in-family와 Own-child 카테고리도 상당한 비율을 차지하고 있습니다. 이는 혼자 사는 비율이 높거나 가족 구성원과의 관계가 많지 않다는 것을 시사하며, 사회적 역할을 가지고 있는 사람들의 많다는 점을 보여줍니다.

 

Race
White 인종이 대다수를 차지하고 있으며, 이는 주로 백인 인구로 구성된 데이터임을 나타냅니다.
다른 인종 카테고리들은 상대적으로 더 적은 비율을 차지하고 있습니다.

 

Sex
남성이 여성보다 더 많은 비율을 차지하고 있습니다.
여성의 비율도 상당하지만 남성에 비해 상대적으로 적습니다.

 

Native Country
United-States가 압도적으로 높은 빈도를 보이며, 이는 대부분의 사람들이 미국 출신임을 나타냅니다.
미국 이외의 다른 국가들은 매우 적은 비율을 차지하고 있으며, 이러한 국가들에서 온 사람들이
전체 데이터셋에서 소수를 차지하고 있음을 보여줍니다.


8. 수치형 feature의 분포 시각화

numeric_columns = df.select_dtypes(include=['int','float']).columns[:-1]

fig, axes = plt.subplots(3, 2, figsize=(13,13))
fig.suptitle('Distribution of numerical Features')

for i, col in enumerate(numeric_columns):
    sns.histplot(df[col], kde=True, bins=30, ax=axes[i//2, i%2])
    axes[i//2, i%2].set_title(f'Distribution of {col}')
    axes[i//2, i%2].set_xlabel('')

plt.tight_layout(rect=[0, 0.03, 1, 0.95])
plt.show()

 

※ 결과 해석

age
대부분의 사람들이 20-50세 사이에 분포해 있습니다.
고령층(70세 이상)은 상대적으로 적은 비율을 차지하고 있습니다.

 

fnlwgt (Final Weight)
fnlwgt 피처는 주로 0에서 400,000 사이에 집중되어 있으며, 매우 극값이 존재합니다.
이 피처의 분포는 왜곡으로 치우쳐 있어, 대부분의 값이 낮은 범위에 치중해 있습니다.

 

education.num
교육 수준은 대부분 8-13 사이에 분포하고 있으며, 이는 고등학교 졸업 이상의 교육을 받은 사람들을 나타냅니다.
더 높은 교육 수준(예: 석사, 박사)은 상대적으로 더 적게 나타납니다.

 

capital.gain
대부분의 사람들의 자본 이득은 0에 가깝게 분포해 있습니다.
일부 사람들은 높은 자본 이득을 보이지만, 이들은 전체에서 소수를 차지합니다.

 

capital.loss
이 피처도 capital.gain과 비슷하게 대부분의 값이 0에 집중되어 있습니다.
높은 자본 손실을 가진 사람들은 상대적으로 매우 적습니다.

 

hours.per.week
대부분의 사람들이 주 30-40시간 근무하며, 이 표준 근무 시간을 나타냅니다.
일부 사람들은 주당 50시간 이상 근무하지만, 이들은 전체에서 소수를 차지합니다.


9. 다중 공선성(VIF) 계산을 통한 피처 상관성 분석

※ 다중 공선성(multicollinearity)

다중 공선성은 회귀 분석에서 독립 변수 간에 높은 상관관계가 존재할 때 발생하는 문제입니다.
이는 독립 변수들이 서로 독립적이지 않고, 한 변수가 다른 변수들로 설명될 수 있을 때 발생합니다.

 

다중 공선성의 문제점

  • 계수의 추정치의 변동이 커집니다: 다중 공선성이 있으면, 회귀 모형의 계수 추정치가 불안정해지고, 표준화에 따라 크게 변할 수 있습니다.
  • 계수의 해석이 어려워집니다: 변수들 간에 높은 상관관계가 있으면, 각 변수의 개별 효과를 정확하게 구분하기 어렵습니다.

다중 공선성의 식별

  • 상관 행렬 확인: 독립 변수들 간의 상관 행렬을 확인하여, 높은 상관관계를 가진 변수를 식별할 수 있습니다.
  • VIF (Variance Inflation Factor) 계산: VIF는 각 독립 변수를 다른 독립 변수들로 회귀시켰을 때의 R^2 값에 기반합니다. VIF가 10 이상이면, 해당 변수는 다중 공선성 문제가 있을 가능성이 높습니다.

다중 공선성의 해결 방법

  • 변수 제거: 상관관계가 높은 변수들 중 하나를 제거할 수 있습니다.
  • 변수 변환: 주성분 분석(PCA) 같은 방법으로 새 독립 변수를 생성할 수 있습니다.

다중 공선성은 회귀 분석의 정확성과 신뢰성에 영향을 줄 수 있으므로, 적절한 전처리가 필요합니다.

import numpy as np
from statsmodels.stats.outliers_influence import variance_inflation_factor

def calculate_vif(df):
    vif_data = pd.DataFrame()
    vif_data["variable"] = df.columns
    vif_data["VIF"] = [variance_inflation_factor(df.values, i) for i in range(df.shape[1])]
    return vif_data

numeric_df = df.select_dtypes(include=['int','float']).dropna()
vif = calculate_vif(numeric_df)
vif

※ 결과 해석

age: VIF 값이 6.8로, 이 변수는 다른 변수들과 중간 수준의 상관관계를 가지고 있습니다. 일반적으로 VIF 값이 10 이상이면 다중 공선성이 있다고 판단하므로, 현재는 경계선 상태입니다.

fnlwgt: VIF 값이 3.6로, 다른 변수들과의 상관관계가 낮습니다. 다중 공선성 문제는 없어 보입니다.

education.num: VIF 값이 11로, 이 변수는 다른 변수들과 높은 상관관계를 가지고 있습니다. 이는 다중 공선성의 문제가 있을 수 있음을 나타냅니다.

capital.gaincapital.loss: VIF 값이 각각 1.08과 1.06로, 이 변수는 다른 변수들과 상관관계가 거의 없습니다.

hours.per.week: VIF 값이 8.7로, 이 변수 역시 다른 변수들과 중간 수준의 상관관계를 가지고 있습니다. 다중 공선성에 대해 주의할 필요가 있습니다.

target: VIF 값이 1.5로, target 변수는 다른 변수들과 상관관계가 낮습니다.

 

결론적으로, education.num 변수가 다중 공선성 문제를 가지고 있을 가능성이 높으며, agehours.per.week 변수도 다중 공선성에 주의해야 합니다. 이 문제를 해결하기 위해 해당 변수들을 제거하거나, 변환을 고려할 수 있습니다.


10. 다중 공선성 확인을 위한 'education' 피처 시각화

# 그림 크기 설정
fig, axs = plt.subplots(figsize=(12, 4), ncols=2)

orders = ['Preschool','1st-4th','5th-6th','7th-8th','9th','10th','11th','12th',
'HS-grad','Some-college','Assoc-acdm','Assoc-voc','Bachelors','Masters','Prof-school','Doctorate']

# 첫 번째 subplot: education 카테고리 시각화
sns.countplot(x="education", data=df, order=orders, ax=axs[0])
axs[0].set_xticklabels(labels = orders, rotation=45)
axs[0].set_title('education')

# 두 번째 subplot: education.num 카테고리 시각화
sns.countplot(x="education.num", data=df, ax=axs[1])
axs[1].set_title('education.num')

plt.tight_layout()
plt.show()

※ 결과 해석

시각화 결과를 통해 확인한 바에 따르면, educationeducation.num 변수가 서로 밀접하게 관련되어 있음이 드러납니다. 구체적으로, education의 각 범주는 education.num에서 특정 숫자 값으로 직접적으로 대응되고 있습니다. 예를 들어, 'HS-grad'는 education.num에서 9의 값을 갖고, 'Bachelors'는 13의 값을 갖습니다. 이는 두 변수가 동일한 정보를 다른 형태로 나타내고 있음을 의미합니다.

이는 VIF 분석에서 본 다중 공선성의 근거가 될 수 있습니다. 그러므로 education과 education.num 중 하나의 변수를 선택하여 모델에 포함시키는 것이 바람직할 수 있습니다.

두 변수를 모두 사용할 경우 정보의 중복으로 인해 회귀 모델의 해석이 복잡해질 수 있으며, 이는 학습에 부정적인 영향을 미칠 수 있습니다.

따라서, 두 변수 중 하나를 선택하여 사용하는 것이 권장됩니다.


11. 교육 수준(education.num)에 따른 직업(occupation) 분포

plt.figure(figsize=(12, 6))

ax = sns.countplot(data=df, x="occupation", hue="education.num")
plt.xticks(rotation=45)
plt.title("Count of Occupation by Education Number")

plt.legend(title="Education Number", loc="upper right")
plt.show()

 

※ 결과 해석

  1. 직업군 별 교육 수준 분포:
    대부분의 직업군에서 특정 교육 수준이 두드러지게 많습니다. 예를 들어, 'Exec-managerial' 및 'Prof-specialty' 직업군은 더 높은 education.num 값을 가진 사람들이 많습니다.
  2. 다양성:
    'Handlers-cleaners' 및 'Craft-repair' 같은 일부 직업군은 교육 수준이 다양하게 분포되어 있습니다.
  3. 고교 졸업 수준:
    많은 직업군에서 교육 수준이 고교 졸업(education.num이 9인 경우)인 경우가 많습니다.
  4. 전문직과 관리자:
    'Prof-specialty' 및 'Exec-managerial' 직업군은 높은 교육 수준을 가진 사람들이 많은 것으로 나타났습니다.

이러한 시각화를 통해 각 직업군의 교육 수준 분포를 더 잘 이해할 수 있으며, 특정 직업군의 높은 교육 수준을 요구하거나,
또는 다양한 교육 수준의 사람들이 종사하고 있는지를 파악할 수 있습니다.


12. 성별(sex)에 따른 주당 근로시간(hours.per.week) 분포

plt.figure(figsize=(10, 5))  

for sex in df['sex'].unique():
    axs = sns.distplot(df[df['sex'] == sex]['hours.per.week'], label=sex)

plt.legend()
plt.title("Distribution of hours.per.week by Sex")
plt.show()

※ 결과 해석

  1. 모양과 중앙값:
  • 남성의 분포는 여성의 분포에 비해 더 넓게 퍼져 있으며, 남성은 여성보다 주당 더 많은 시간을 일하는 경향이 있습니다.
  • 두 성별 모두 주당 근무 시간의 중앙값은 40시간 근처에 위치해 있습니다.
  1. 분포의 뾰족함(커토시스):
  • 여성의 분포는 남성의 분포보다 더 뾰족합니다.
  • 이는 여성이 특정 주당 근무 시간에 더 집중되어 있음을 의미합니다.
  1. 극단값:
  • 남성의 분포는 여성에 비해 극단값이 더 많이 관찰됩니다.
  • 일부 남성은 주당 60시간 이상 일하는 반면, 여성은 그렇게 많지 않은 것으로 보입니다.
  1. 밀도:
  • 여성은 주로 30-40시간의 근무 시간에 집중되어 있는 반면, 남성은 40-50시간에 더 많이 분포하고 있습니다.

결론

  • 그래프를 통해 여성은 일반적으로 주당 30-40시간 근무하는 반면, 남성은 주당 40-50시간, 때로는 그 이상 근무하는 경향이 있음을 알 수 있습니다.

13. 변수 간 상관 관계 시각화

corr_matrix = df.corr()

# Create the heatmap
axs = sns.heatmap(corr_matrix, annot=True, fmt=".2f")

# Set the title of the plot
plt.title('Correlation Matrix')

# Show the plot
plt.show()

 

※ 결과 해석

 

  • education.numtarget은 약 0.35의 상관계수를 가지고 있으며, 이는 교육 수준이 높을수록 소득이 50K를 초과할 가능성이 높다는 것을 나타냅니다.
  • hours.per.weektarget은 약 0.23의 상관계수를 가지고 있습니다. 이는 주당 더 많은 시간을 일할수록 소득이 50K를 초과할 가능성이 높다는 것을 나타냅니다.
  • agetarget도 약 0.24의 상관계수를 가지며, 나이가 많을수록 소득이 50K를 초과할 가능성이 높다는 것을 나타냅니다.
  • capital.gaincapital.losstarget과 약의 상관관계를 가지지만, 이들 피처의 대부분 값은 0이므로 상관계수가 실제 관계를 정확하게 반영하지 않을 수 있습니다.

14. 범주형 변수와 소득(target)의 분포

fig, axes = plt.subplots(3, 2, figsize=(20, 18))
fig.suptitle('Categorical Features vs Target Visualization')

# workclass vs Target (Grouped Bar Plot)
sns.countplot(x='workclass', hue='target', data=df, ax=axes[0, 0])
axes[0, 0].set_title('workclass vs Target')
axes[0, 0].tick_params(axis='x', rotation=45)

# relationship vs Target (Grouped Bar Plot)
sns.countplot(x='relationship', hue='target', data=df, ax=axes[0, 1])
axes[0, 1].set_title('relationship vs Target')
axes[0, 1].tick_params(axis='x', rotation=45)

# education vs Target (Stacked Bar Plot)
education_target_counts = df.groupby(['education', 'target']).size().unstack()

education_target_counts.plot(kind='bar', stacked=True, ax=axes[1, 0])
axes[1, 0].set_title('education vs Target')
axes[1, 0].set_ylabel('Count')

# sex vs Target (Stacked Bar Plot)
sex_target_counts = df.groupby(['sex', 'target']).size().unstack()

sex_target_counts.plot(kind='bar', stacked=True, ax=axes[1,1])
axes[1,1].set_title('sex vs Target')
axes[1,1].set_ylabel('Count')

# occupation vs Target (Heatmap)
occupation_crosstab = pd.crosstab(df['occupation'], df['target'], normalize='index')
sns.heatmap(occupation_crosstab, annot=True, fmt='.2f', cmap="YlGnBu", ax=axes[2, 0])
axes[2, 0].set_title('occupation vs Target')

# race vs Target (Heatmap)
race_crosstab = pd.crosstab(df['race'], df['target'], normalize='index')
sns.heatmap(race_crosstab, annot=True, fmt='.2f', cmap="YlGnBu", ax=axes[2, 1])
axes[2, 1].set_title('race vs Target')

plt.tight_layout(rect=[0, 0.03, 1, 0.95])
plt.show()

 

 

※ 결과 해석

workclass vs Target (Grouped Bar Plot)
이 그래프는 각 workclass 범주에서 Target 변수의 분포를 보여줍니다.

대부분의 사람들이 Private 클래스에 속해 있으며, 이 계층에서 소득이 낮은 경우가 많은 것으로 보입니다.

 

relationship vs Target (Grouped Bar Plot)
relationship 상태에 따른 타겟 변수의 분포를 보여줍니다.

Husband(남편) 관계 상태에서 소득이 높은 사람들의 비율이 상대적으로 높은 것으로 나타납니다.

 

education vs Target (Stacked Bar Plot)
교육 수준(education)에 따른 타겟 변수의 분포를 나타냅니다.

높은 교육 수준(예: Bachelors, Masters, Doctorate)를 가진 사람들 사이에서 소득이 높은 사람들의 비율이 더 높게 나타납니다.

 

sex vs Target (Stacked Bar Plot)
성별(sex)에 따른 타겟 변수의 분포를 보여줍니다.

남성에서 소득이 높은 비율이 여성에 비해 더 높은 것으로 보입니다.

 

occupation vs Target (Heatmap)
직업(occupation)에 따른 타겟 변수의 분포를 히트맵으로 나타냅니다.

Exec-managerial과 Prof-specialty 직업군에서 소득이 높은 사람들의 비율이 상대적으로 높습니다.

 

race vs Target (Heatmap)
인종(race)에 따른 타겟 변수 분포를 히트맵으로 나타냅니다.

모든 인종에서 소득이 낮은 사람들이 더 많지만, White와 Asian-Pac-Islander 인종 그룹에서 소득이 높은 사람의 비율이 상대적으로 높습니다.


15. 수치형 변수와 소득(target)의 분포: 히스토그램 및 바이올린 플롯

fig, axs = plt.subplots(len(numeric_columns), 2, figsize=(12, 15))
fig.suptitle('Numerical Features vs Target')

for i, col in enumerate(numeric_columns):

    # 히스토그램(Histogram)
    sns.histplot(df, x=col, hue='target', multiple="stack", ax=axs[i, 0], kde=True)
    axs[i, 0].set_title(f'Histogram of {col}')
    
    # 바이올린 플롯(Violin Plot)
    sns.violinplot(x='target', y=col, data=df, ax=axs[i, 1])
    axs[i, 1].set_title(f'Violin Plot of {col}')

plt.tight_layout(rect=[0, 0.03, 1, 0.95])
plt.show()

 

※ 결과 해석

age:

  • 히스토그램: 나이가 증가함에 따라 50K 이상을 벌어들이는 사람의 비율이 증가하는 것을 알 수 있습니다. 20-30대 초반에서는 50K 이상을 벌어들이는 사람들이 상대적으로 적지만, 나이가 들어감에 따라 그 비율이 증가합니다.
  • 바이올린 플롯: 바이올린 플롯에서도 비슷한 추세를 확인할 수 있습니다. 50K 이상을 벌어들이는 그룹은 나이가 더 많은 분포를 보이고 있습니다.

fnlwgt (Final Weight):

  • 히스토그램: 두 그룹 사이에 큰 차이가 보이지 않으며, 대부분의 사람들이 낮은 fnlwgt 값을 가지고 있습니다.
  • 바이올린 플롯: 여기에서도 두 그룹 사이에 큰 차이를 보이지 않습니다.

education.num:

  • 히스토그램: 교육 수준이 높은 사람들이 50K 이상을 벌어들일 가능성이 더 높습니다.
  • 바이올린 플롯: 교육 수준이 높을수록 50K 이상을 벌어들이는 비율이 높아지는 것을 알 수 있습니다.

capital-gain:

  • 히스토그램: 대부분의 사람들이 0에 가까운 capital-gain 값을 가지고 있으며, 50K 이상을 벌어들이는 사람들만이 높은 capital-gain 값을 가지는 경향이 있습니다.
  • 바이올린 플롯: 비슷한 패턴이 나타나며, 50K 이상을 벌어들이는 그룹에서만 capital-gain 값이 더 높게 나타나는 분포를 볼 수 있습니다.

capital-loss:

  • 히스토그램: capital-loss도 대부분의 사람들이 0에 가깝게 분포되어 있지만, 몇몇 사람들은 높은 capital-loss 값을 가지고 있습니다.
  • 바이올린 플롯: capital-gain과 비슷한 패턴이 보입니다. 두 그룹 간의 큰 차이는 보이지 않습니다.

hours-per-week:

  • 히스토그램: 50K 이상을 벌어들이는 사람들이 일주일에 더 많은 시간을 일하는 경향이 있습니다.
  • 바이올린 플롯: 일주일의 근무 시간이 길수록 50K 이상을 벌어들이는 비율이 높아지는 것을 확인할 수 있습니다.

16. 나이(age) 및 교육 수준(education)에 따른 분포

g = sns.catplot(data=df, x="age", y="education", hue="target", kind='box')
axs = g.facet_axis(0, 0) 
plt.show()

 

※ 결과 해석

Education Level:

  • 대부분의 교육 수준에서 나이의 중앙값은 대략 비슷한 분포를 보이고 있습니다.
  • Preschool 수준에서는 나이대가 다소 낮게 나타나며, 이는 이 수준의 교육을 받은 사람들이 상대적으로 젊은 연령대에 분포해 있음을 나타냅니다.
  • Doctorate 및 Prof-school 교육 수준에서는 나이대가 높게 나타나며, 이는 해당 교육 수준을 이수하는데 상대적으로 더 많은 시간이 소요됨을 나타냅니다.

Target:

  • target 값에 따라 각 교육 수준의 나이 분포에 차이가 있습니다. 소득이 50K 이상인 그룹은 일반적으로 50K 이하인 그룹보다 나이가 더 높게 분포해 있는 것으로 보입니다.

Outliers:

  • 박스 플롯에서 이상치로 표시된 데이터는 각 교육 수준에서 일반적인 나이 범위에서 벗어난 값들입니다.
  • Bachelors, Masters, Prof-school, Doctorate 수준에서 50K 이상의 소득을 가진 그룹에서 이상치가 더 많이 관찰됩니다.

Age Distribution:

  • 나이 분포는 교육 수준에 따라 다르며, 특히 고등 교육을 받은 그룹에서 더 넓게 분포하는 것으로 보입니다.