공모전/데이터분석

데이터 분석 공모전 작업1

진강이 2024. 1. 26. 19:35
import pandas as pd
import numpy as np
file_path = 'rawdata.csv'
df = pd.read_csv(file_path) #read_csv 함수로 데이를 df형태로 불러옴
df.head()
  ID Q1A1 Q1A2 Q2A11 Q2A12 Q2A13 Q2A2 Q2A3 Q3 Q4A1 ... ADQ8A4 ADQ8A5 ADQ8A6 ADQ8A7 ADQ8A8 ADQ9 ADQ101 ADQ102 ADQ103 WT2
0 108121 1 2 1.0 NaN NaN 2 2 1 1 ... NaN NaN NaN NaN NaN 3 3 1 1 1.07
1 106029 1 2 1.0 NaN NaN 2 2 1 1 ... NaN NaN NaN NaN NaN 2 13 1 2 0.67
2 100438 2 2 1.0 NaN NaN 2 2 1 1 ... NaN NaN NaN NaN NaN 3 6 1 1 0.65
3 100436 2 2 1.0 NaN NaN 2 2 1 1 ... NaN NaN NaN NaN NaN 5 6 1 1 0.63
4 101436 2 2 1.0 NaN NaN 2 2 1 1 ... NaN NaN NaN NaN NaN 1 17 1 1 0.40

5 rows × 234 columns

y값 설정

# y값은 디지털 정보화 수준(종합) = 접근(0.2)+역량(0.4)+활용(0.4)
cols = list(df.columns)
level1 = cols[1:9] #접근에 해당하는 질문
level2 = cols[9:23] #역량에 해당하는 질문
level3 = cols[23:77] + cols[192:211] #활용에 해당하는 질문
df = df.fillna(0)
df = df.astype(int)
df.head()
  ID Q1A1 Q1A2 Q2A11 Q2A12 Q2A13 Q2A2 Q2A3 Q3 Q4A1 ... ADQ8A4 ADQ8A5 ADQ8A6 ADQ8A7 ADQ8A8 ADQ9 ADQ101 ADQ102 ADQ103 WT2
0 108121 1 2 1 0 0 2 2 1 1 ... 0 0 0 0 0 3 3 1 1 1
1 106029 1 2 1 0 0 2 2 1 1 ... 0 0 0 0 0 2 13 1 2 0
2 100438 2 2 1 0 0 2 2 1 1 ... 0 0 0 0 0 3 6 1 1 0
3 100436 2 2 1 0 0 2 2 1 1 ... 0 0 0 0 0 5 6 1 1 0
4 101436 2 2 1 0 0 2 2 1 1 ... 0 0 0 0 0 1 17 1 1 0

5 rows × 234 columns

# 최종 y값
df['y_value'] = 0

# 접근 계산
for col in level1:
    df.loc[:, 'y_value'] += df.loc[:, col]*0.2

# 역량 계산
for col in level2:
    df.loc[:, 'y_value'] += df.loc[:, col]*0.4

# 활용 계산
for col in level3:
    df.loc[:, 'y_value'] += df.loc[:, col]*0.4
# 라벨 생성 - 이 라벨 생성이 관건인데....이건 도메인 지식이 필요해서....
df['y_label'] = 0

df.loc[df['y_value']<40, 'y_label'] = 1
df.loc[(df['y_value']>=40)&(df['y_value']<85), 'y_label'] = 2
df.loc[df['y_value']>=85, 'y_label'] = 3

일단 이 디지털 정보화 수준을 y값이라 놨어. 괄호안에 있는 값은 가중치야. 접근, 역량, 활용에 대해 묻는 질문은 내가 엑셀 파일에 색깔로 구별해놈 (저 지표는 NIA에서 설정한 공식)

df.loc[:, 'y_value'].describe()
count    2300.000000
mean       67.840000
std        27.747736
min        16.200000
25%        52.800000
50%        68.000000
75%        86.000000
max       153.800000
Name: y_value, dtype: float64
df['y_label'].value_counts()
2    1357
3     599
1     344
Name: y_label, dtype: int64

X 값 설정

X_cols = cols[211:217] + cols[218:220] + cols[229:233]
X_df = df.loc[:, X_cols]

X_col_name = ['연령', '성별', '직업', '고용주여부', '최종학력', '장애구분', '가구_거주형태', '가구구성형태', '월평균소득', '현재거주지역',
            '지역구분(시/군)', '지역구분(읍/면/동)']

X_df.columns = X_col_name
X_df
  연령 성별 직업 고용주여부 최종학력 장애구분 가구_거주형태 가구구성형태 월평균소득 현재거주지역 지역구분(시/군) 지역구분(읍/면/동)
0 70 2 11 0 1 1 2 2 3 3 1 1
1 59 1 14 0 2 1 1 2 2 13 1 2
2 70 1 14 0 2 1 1 2 3 6 1 1
3 62 1 9 0 3 1 3 2 5 6 1 1
4 65 2 6 0 1 1 1 2 1 17 1 1
... ... ... ... ... ... ... ... ... ... ... ... ...
2295 61 2 11 0 3 1 2 2 7 9 1 1
2296 69 1 14 0 1 1 1 1 1 17 1 2
2297 75 1 14 0 1 1 1 2 2 11 1 1
2298 78 2 9 0 3 1 3 2 3 9 1 1
2299 85 2 14 0 1 1 1 2 1 17 1 1

2300 rows × 12 columns

main data 생성

main_df = pd.concat([X_df, df.loc[:, ['y_value', 'y_label']]], axis=1) #x,y 합침
main_df
  연령 성별 직업 고용주여부 최종학력 장애구분 가구_거주형태 가구구성형태 월평균소득 현재거주지역 지역구분(시/군) 지역구분(읍/면/동) y_value y_label
0 70 2 11 0 1 1 2 2 3 3 1 1 47.0 2
1 59 1 14 0 2 1 1 2 2 13 1 2 43.4 2
2 70 1 14 0 2 1 1 2 3 6 1 1 41.6 2
3 62 1 9 0 3 1 3 2 5 6 1 1 50.0 2
4 65 2 6 0 1 1 1 2 1 17 1 1 37.6 1
... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
2295 61 2 11 0 3 1 2 2 7 9 1 1 28.6 1
2296 69 1 14 0 1 1 1 1 1 17 1 2 28.4 1
2297 75 1 14 0 1 1 1 2 2 11 1 1 25.2 1
2298 78 2 9 0 3 1 3 2 3 9 1 1 28.4 1
2299 85 2 14 0 1 1 1 2 1 17 1 1 19.4 1

2300 rows × 14 columns

#!pip install lightgbm
#!pip install scikit-learn
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
import lightgbm as lgb

from sklearn.metrics import accuracy_score

데이터 분리

X = X_df
y = main_df.loc[:, 'y_label']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

X_train.shape, X_test.shape
((1840, 12), (460, 12))

랜덤포레스트

rf = RandomForestClassifier()

# 데이터 학습
rf.fit(X_train, y_train)

# 예측값 생성
y_pred = rf.predict(X_test)

# 변수 중요도 확인
feature_importances = rf.feature_importances_
feature_importance_df = pd.DataFrame({'Feature': X.columns, 'Importance': feature_importances})
feature_importance_df = feature_importance_df.sort_values(by='Importance', ascending=False)

# 정확도 확인
accuracy = accuracy_score(y_test, y_pred)
print("테스트 세트 정확도:", accuracy)

feature_importance_df
테스트 세트 정확도: 0.6695652173913044
  Feature Importance
0 연령 0.243566
9 현재거주지역 0.184022
8 월평균소득 0.136333
2 직업 0.124269
4 최종학력 0.118282
6 가구_거주형태 0.065725
1 성별 0.033850
11 지역구분(읍/면/동) 0.025739
3 고용주여부 0.024871
7 가구구성형태 0.019679
10 지역구분(시/군) 0.015843
5 장애구분 0.007821
main_df
  연령 성별 직업 고용주여부 최종학력 장애구분 가구_거주형태 가구구성형태 월평균소득 현재거주지역 지역구분(시/군) 지역구분(읍/면/동) y_value y_label
0 70 2 11 0 1 1 2 2 3 3 1 1 47.0 2
1 59 1 14 0 2 1 1 2 2 13 1 2 43.4 2
2 70 1 14 0 2 1 1 2 3 6 1 1 41.6 2
3 62 1 9 0 3 1 3 2 5 6 1 1 50.0 2
4 65 2 6 0 1 1 1 2 1 17 1 1 37.6 1
... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
2295 61 2 11 0 3 1 2 2 7 9 1 1 28.6 1
2296 69 1 14 0 1 1 1 1 1 17 1 2 28.4 1
2297 75 1 14 0 1 1 1 2 2 11 1 1 25.2 1
2298 78 2 9 0 3 1 3 2 3 9 1 1 28.4 1
2299 85 2 14 0 1 1 1 2 1 17 1 1 19.4 1

2300 rows × 14 columns

# 수정된 코드: 키와 값의 형태를 맞춤
dic = {
    1: 'Seoul',
    2: 'Busan',
    3: 'Daegu',
    4: 'Incheon',
    5: 'Gwangju',
    6: 'Daejeon',
    7: 'Ulsan',
    8: 'Sejong',
    9: 'Gyeonggi',
    10: 'Gangwon',
    11: 'Chungbuk',
    12: 'Chungnam',
    13: 'Jeonbuk',
    14: 'Jeonnam',
    15: 'Gyeongbuk',
    16: 'Gyeongnam',
    17: 'Jeju',
    99: 'No Response'}
# 함수 정의
def make_graph(ax, df, i):
    # seaborn을 사용한 버전
    sns.countplot(x='y_label', data=df, ax=ax)
    ax.set_title(f'Distribution of {dic[i]}')
import matplotlib.pyplot as plt
import seaborn as sns

# 그룹핑
loc_group = main_df.groupby('현재거주지역')

# subplot 설정
fig, axes = plt.subplots(4, 4, figsize=(15, 12))
fig.suptitle('Distribution of Each Region', fontsize=20)

# 각 그래프를 하위 그래프에 그림
for i, ax in zip(range(1, 17), axes.flatten()):
    new_df = loc_group.get_group(i)
    make_graph(ax, new_df, i)

# 빈 하위 그래프는 숨김
for ax in axes.flatten()[len(loc_group.groups):]:
    ax.axis('off')

# 상하 간격 조절
plt.subplots_adjust(top=0.9, bottom=0.1, hspace=0.4)    

# 그래프 출력
plt.show()