이번 포스팅은 3-1학기 데이터마이닝 수업 기말 개인프로젝트로 제출했던 전세계 1985-2016 자살률 분석 건이다.
자유주제여서 주제를 고민하다가 캐글에서 흥미로운 데이터를 찾아 가져왔다.
1. 분석할 데이터 및 목표
- 분석할 데이터: Suicide Rates Overview 1985 to 2016 from Kaggle
- 목표: 전세계 자살률을 알아보고, 각 속성이 자살률에 영향을 미치는지 그리고 어느 속성이 가장 영향을 미치는지 분석
https://www.kaggle.com/russellyates88/suicide-rates-overview-1985-to-2016
- DataSet
. Columns: 12개
country, year, sex, age, suicides_no, population, suicides/100k pop, country-year, HDI for year,
gdp_for_year ($), gdp_per_capita ($), generation
. Rows count: 27820개
2. 전처리 과정
1) 패키지 선언
#데이터분석용 pkg
import pandas as pd
import numpy as np
import random as rnd #시각화용 pkg
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline #기계학습
from sklearn.linear_model
import LogisticRegression from sklearn.svm
import SVC, LinearSVC from sklearn.ensemble
import RandomForestClassifier from sklearn.neighbors
import KNeighborsClassifier from sklearn.naive_bayes
import GaussianNB from sklearn.linear_model
import Perceptron from sklearn.linear_model
import SGDClassifier from sklearn.tree
import DecisionTreeClassifier from sklearn.neural_network
import MLPClassifier
2) 데이터 로딩 및 확인
#데이터로딩
data = pd.read_csv('master.csv') # 데이터 시각화용. 원본
data_train = pd.read_csv('master_train.csv') #원본 데이터를 7:3으로 train:test로 편집함
data_test = pd.read_csv('master_test.csv') #train:70%, test:30%
print ("Data_train shape:", data_train.shape, "\n")
print ("Data_test shape:", data_test.shape, "\n")
print (data_train.info())
print('_'*40)
print (data_tnfo())
* 핵심 속성인 자살률에 대해 mean 값을 확인해봄
#suicides/100k pop의 mean 값 확인=12.16
data_train.describe()
#suicides/100k pop의 mean 값 확인=14.35
data_test.describe()
3) Missing Data 확인
: Missing Data가 많은 속성값은 해당 속성에 따라 결과값이 나온다고 가정하기 어려우므로 삭제 위함
#check missing values in test dataset
print(data_train.isnull().sum())
print('_'*40)
print(data_test.isnull().sum())
# 몇프로가 누락되었는지 퍼센트로 확인 = 0.6869 => 약 70% 누락
sum(pd.isnull(data_train['HDI for year']))/len(data_train["HDI for year"])
4) 누락 및 중복값 삭제
# 누락 및 중복값 Data 삭제. 70%가 누락된 HDI for year
data_train.drop('HDI for year', axis=1, inplace=True)
data_test.drop('HDI for year', axis=1, inplace=True)
#suicides_no와 population을 나눈 값이 'suicides/100k pop' * 10^-5 이므로 중복 속성 제거.
data_train.drop('suicides_no', axis=1, inplace=True)
data_train.drop('population', axis=1, inplace=True)
data_train.drop('country-year', axis=1, inplace=True)
# country 및 year 속성 별도 존재하여 삭제
data_train.drop(' gdp_for_year ($) ', axis=1, inplace=True)
#gdp_per_capita($)와 비례하므로 중복 속성. 삭제
data_train['age']=data['age'].str.strip(" years") # years 텍스트 제거
data_test.drop('suicides_no', axis=1, inplace=True)
data_test.drop('population', axis=1, inplace=True)
data_test.drop('country-year', axis=1, inplace=True)
# country 및 year 속성 별도 존재하여 삭제
data_test.drop(' gdp_for_year ($) ', axis=1, inplace=True)
#gdp_per_capita($)와 비례하므로 중복 속성. 삭제
data_test['age']=data['age'].str.strip(" years") # years 텍스트 제거 data_train.head()
5) 새로운 속성값 생성
- Over_mean_suicides: 평균보다 자살률이 클 경우 1, 작을 경우 0으로 열 추가
# 신규 속성인 Over_mean_suicides 만들어줌. 자살률이 전체 mean 자살률대비 크면 1, 작으면 0
# 해당 속성이 0보다 크면 1, 아니면 0
data_train['Over_mean_suicides'] = np.where(data_train['suicides/100k pop']>12.16, 1, 0) data_test['Over_mean_suicides'] = np.where(data_test['suicides/100k pop']>14.35, 1, 0)
data_train.head()
2. 데이터 시각화 및 간단 분석
1) 국가(Country)별 자살률 확인 및 시각화
2) 년도(year)별 자살률 확인 및 시각화
3) 성별(Sex)별 자살률 확인 및 시각화
4) 연령(age)별 자살률 확인 및 시각화
5) 1인당 GDP(gdp_per_capita($)) 별 자살률 확인 및 시각화
6) 세대(Generation)별 자살률 확인 및 시각화
1) 국가별 자살률 확인 및 상위 5개 국가 출력
#1) 국가별 자살률 확인
fig = plt.figure(figsize=(20,5))
plt.title('Suicide Rates by Country')
sns.barplot(x='country', y='suicides/100k pop', data=data[['country', 'suicides/100k pop']].groupby('country', as_index=False).mean().sort_values(by='suicides/100k pop', ascending=False)); plt.xticks(rotation=90);
#x축(country) 회전 # 상위 5개 국가 출력 ==> 상위5국가: 리투아니아, 스리랑카, 러시아, 헝가리, 벨라루스 // 한국: 11위 data[['country','suicides/100k pop']].groupby('country', as_index=False).mean().sort_values(by='suicides/100k pop', ascending=False).head()
2) 년도별 자살률 시각화 및 상위 5개 년도 출력
: 1995년대 자살률이 높다. 이유는? 뒤에서...
#2)년도(year)별 자살률 확인 및 시각화 #시각화
fig, ax = plt.subplots(figsize=(20, 5))
plt.title('Suicide rates by year')
sns.lineplot(x='year', y='suicides/100k pop', data=data[['year','suicides/100k pop']].groupby('year',as_index=False).mean().sort_values(by='year',ascending=True),marker='o',color='RED');
ax.set(xticks=data['year'].unique());
# 상위 5개 년도 출력 ==> 상위5국가: 리투아니아, 스리랑카, 러시아, 헝가리, 벨라루스 // 한국: 11위
data[['year', 'suicides/100k pop']].groupby('year', as_index=False).mean().sort_values(by='suicides/100k pop', ascending=False).head()
3) 성별에 따른 자살률 확인 및 순위 출력
: 남성이 여성대비 4배이상 자살률이 높다.
#3) 성별(Sex)별 자살률 확인 및 시각화 => 남성이 여성 대비 4배 높음
fig = plt.figure(figsize=(2,3))
plt.title('Suicide rates by sex') sns.barplot(x='sex', y='suicides/100k pop', data=data[['sex', 'suicides/100k pop']].groupby('sex', as_index=False).mean().sort_values(by='suicides/100k pop', ascending=False)); data[['sex','suicides/100k pop']].groupby('sex', as_index=False).mean().sort_values(by='suicides/100k pop', ascending=False)
4) 연령대에 따른 자살률 확인 및 순위출력
: 고령일수록 자살률이 높다.
#4) 연령(age)별 자살률 확인 및 시각화 ==> 고령일수록, 남성일수록 자살률이 높다. fig=plt.figure(figsize=(5,4)); plt.title('Suicide rates by Age')
sns.barplot(x='age', y='suicides/100k pop',hue='sex', data=data[['age','suicides/100k pop','sex']].groupby(['age','sex'],as_index=False).mean().sort_values(by='suicides/100k pop',ascending=False));
data[['age','suicides/100k pop']].groupby('age', as_index=False).mean().sort_values(by='suicides/100k pop', ascending=False)
5) 1인당 GDP(gdp_per_capita($))별 자살률 확인 및 시각화
: GDP는 자살률과 관련이 없는 것으로 추측된다.
#5) 1인당 GDP(gdp_per_capita($)) 별 자살률 확인 및 시각화 ==> GDP와 자살률은 관련이 없다. 높든 낮든 자살률의 분포는 유사하다.
fig = plt.figure(figsize=(30,10))
plt.title('Suicide rates by gdp_per_capita ($)') sns.barplot(x='gdp_per_capita ($)', y='suicides/100k pop', data=data[['gdp_per_capita ($)', 'suicides/100k pop']].groupby('gdp_per_capita ($)', as_index=False).mean().sort_values(by='suicides/100k pop', ascending=False));
#data[['gdp_per_capita ($)','suicides/100k pop']].groupby('gdp_per_capita ($)', as_index=False).mean().sort_values(by='suicides/100k pop', ascending=False) data['gdp_per_capita ($)'].describe()
6) Generation에 따른 자살률 확인
: Generation X(세계 2차대전 이후, 대략 1970년대생), Silent 세대 (1920-40년대생. 유년기를 전쟁통으로 겪은, 조용히 지낼 수 밖에 없었던 세대) 자살률이 가장 높다.
6)generation별 자살률 및 시각화 => Genearation X세대 자살률이 가장 높음
f,ax=plt.subplots(1,2,figsize=(15,5)) data['generation'].value_counts().plot.pie(explode=[0.1,0.1,0.1,0.1,0.1,0.1],autopct='%1.1f%%',ax=ax[0],shadow=True)
ax[0].set_title('Suicide Rates by Generation') ax[0].set_ylabel('Suicides/100k pop') sns.countplot('generation',data=data,ax=ax[1]) ax[1].set_title('Suicide Rates by Generation')
plt.show() data[['generation','suicides/100k pop']].groupby('generation', as_index=False).mean().sort_values(by='suicides/100k pop', ascending=False)
* 데이터마이닝 과제에서는 속성별 분석은 여기까지만 진행했으나
데이터시각화 과목 프로젝트에서도 해당 주제를 선택하여
엑셀을 통해 추가적 분석을 진행하였다. 이또한 나름 시각화이므로 중간에 끼워넣어본다!!
다시 데이터마이닝으로 돌아와서...
3. Machine Learning 기법을 활용한 자살률 예측
- 사용 알고리즘
1) Logistic Regression
2) Support Vector Machines
3) Decision Tree
4) KNN
5) Naive Bayes
6) Linear SVC
7) Perceptron
8) Random Forest
9) Stochastic Gradient Decent
3-1) 데이터 추가 전처리: string값을 정수형으로 변환
#1) age 의 string을 정수로 바꾸기
def func(dataset): if dataset['age'] == '75+': # 75+ ==> 80 치환
return '80'
elif dataset['age'] =='55-74': # 55-74 ==> 65 치환
return '65'
elif dataset['age'] =='35-54': # 35-54 ==> 45 치환
return '45'
elif dataset['age'] =='25-34': # 25-34 ==> 30 치환
return '30'
elif dataset['age'] =='15-24': # 15-24 ==> 20 치환
return '20'
else: return '10' # 5-14 = 10 치환
#TrainData 적용
data_train['age'] = data_train.apply(func, axis=1)
data_train[['age','suicides/100k pop']].groupby('age', as_index=False).mean().sort_values(by='suicides/100k pop', ascending=False)
#TestData도 같이 적용
data_test['age'] = data_test.apply(func, axis=1)
data_test[['age','suicides/100k pop']].groupby('age', as_index=False).mean().sort_values(by='suicides/100k pop', ascending=False)
2) sex의 string을 정수로 바꾸기
def func(dataset): if dataset['sex'] == 'female': # 여자 = 0 으로 치환
return '0' else: return '1' # 남자 = 1 로 치환. spelling이 겹치므로 여자부터 치환해야함.
data_train['sex'] = data_train.apply(func, axis=1)
data_train[['sex','suicides/100k pop']].groupby('sex', as_index=False).mean().sort_values(by='suicides/100k pop', ascending=False) data_test['sex'] = data_test.apply(func, axis=1)
data_test[['sex','suicides/100k pop']].groupby('sex', as_index=False).mean().sort_values(by='suicides/100k pop', ascending=False)
3) Generation 의 string을 정수로 바꾸기
def func(dataset):
if dataset['generation'] == 'G.I. Generation': # G.I generation = 1
return '1'
elif dataset['generation'] =='Silent': # Silent = 2
return '2'
elif dataset['generation'] =='Boomers': # Boomers = 3
return '3'
elif dataset['generation'] =='Generation X': # Generation X = 4
return '4'
elif dataset['generation'] =='Millenials': # Millenials = 5
return '5'
else:
return '6' # Generation Z = 6
data_train['generation'] = data_train.apply(func, axis=1)
data_train[['generation','suicides/100k pop']].groupby('generation', as_index=False).mean().sort_values(by='suicides/100k pop', ascending=False)
data_test['generation'] = data_test.apply(func, axis=1)
data_test[['generation','suicides/100k pop']].groupby('generation', as_index=False).mean().sort_values(by='suicides/100k pop', ascending=False)
3-2) 학습집합 및 테스트 집합 준비
: 만들어 준 속성(Over_mean_suicides)을 예측값으로 사용.
이에 영향을 미치는 요소인 suicides/100k pop 은 제거하고, Country의 경우 나라가 100개이상이므로
String제거 복잡하여 속성 제거
- 비율: Training data(19474, 70%), Test Data(8346, 30%)
X_train = data_train.drop("Over_mean_suicides", axis=1)
X_train = X_train.drop("suicides/100k pop" , axis =1)
X_train = X_train.drop("country", axis=1) Y_train = data_train["Over_mean_suicides"]
X_test = data_test.drop("Over_mean_suicides" , axis=1).copy()
X_test = X_test.drop("suicides/100k pop" , axis =1)
X_test = X_test.drop("country" , axis =1)
X_train.shape, Y_train.shape, X_test.shape
3-3) 알고리즘 시작
#1. Logistic Regression
logreg = LogisticRegression(solver='lbfgs')
logreg.fit(X_train, Y_train)
Y_pred = logreg.predict(X_test)
acc_log= round(logreg.score(X_train, Y_train) * 100, 2)
acc_log
#2. Support Vector Machines
svc = SVC() solver='liblinear' svc.fit(X_train, Y_train)
Y_pred = svc.predict(X_test)
acc_svc = round(svc.score(X_train, Y_train) * 100, 2)
print(acc_svc)
#3. Decision Tree
decision_tree = DecisionTreeClassifier()
decision_tree.fit(X_train, Y_train)
Y_pred = decision_tree.predict(X_test)
acc_decision_tree = round(decision_tree.score(X_train, Y_train) * 100, 2)
acc_decision_tree
# 4. KNN
knn = KNeighborsClassifier(n_neighbors = 3)
knn.fit(X_train, Y_train)
Y_pred = knn.predict(X_test)
acc_knn = round(knn.score(X_train, Y_train) * 100, 2)
acc_knn
# 5. Gaussian Naive Bayes
gaussian = GaussianNB() gaussian.fit(X_train, Y_train)
Y_pred = gaussian.predict(X_test)
acc_gaussian = round(gaussian.score(X_train, Y_train) * 100, 2)
acc_gaussian
# 6. Linear SVC
linear_svc = LinearSVC()
linear_svc.fit(X_train, Y_train)
Y_pred = linear_svc.predict(X_test)
acc_linear_svc = round(linear_svc.score(X_train, Y_train) * 100, 2)
acc_linear_svc
# 7. Perceptron perceptron = Perceptron()
perceptron.fit(X_train, Y_train)
Y_pred = perceptron.predict(X_test)
acc_perceptron = round(perceptron.score(X_train, Y_train) * 100, 2)
acc_perceptron
#8. Random Forest
random_forest = RandomForestClassifier(n_estimators=100)
random_forest.fit(X_train, Y_train)
Y_pred = random_forest.predict(X_test)
random_forest.score(X_train, Y_train)
acc_random_forest = round(random_forest.score(X_train, Y_train) * 100, 2)
acc_random_forest
#9. Stochastic Gradient Descent
sgd = SGDClassifier() sgd.fit(X_train, Y_train)
Y_pred = sgd.predict(X_test)
acc_sgd = round(sgd.score(X_train, Y_train) * 100, 2)
acc_sgd
3-4. 알고리즘별 Score 정렬
models = pd.DataFrame({ 'Model': ['Support Vector Machines', 'KNN', 'Logistic Regression', 'Random Forest', 'Naive Bayes', 'Perceptron', 'Stochastic Gradient Decent', 'Linear SVC', 'Decision Tree'], 'Score': [acc_svc, acc_knn, acc_log, acc_random_forest, acc_gaussian, acc_perceptron, acc_sgd, acc_linear_svc, acc_decision_tree]}) models.sort_values(by='Score', ascending=False)
3-5) 최종 파일 생성
submission = pd.DataFrame({ "Country": data_test["country"], "If_over_mean_of_suicide": Y_pred }) submission.to_csv('final_pjt_20.csv', index=False) data_final = pd.read_csv('final_pjt_20.csv') data_final.info() data_final.describe()
결론적으로 전세계 자살률은 남성일수록, 고령일수록, gdp와는 관계가 없고, 전쟁과 가까운 세대일수록 높았다.
개인적인 생각으로는 못사는 나라일수록 자살률이 높다기보다는, 본인이 처한 경험과 환경에 따라 다른 것이 아닐까 생각이 든다. 후진국의 사람들은 다른 나라를 경험해보았을까? TV조차 없을텐데 그들에게 비교대상은 그 주위사람들뿐이지 않을까. 특히 나이가 먹을수록 몸도 마음도 약해지고, 주도적으로 할 수 있는 것 조차 한계가 생기기 때문에 안좋은 생각을 하기 상대적으로 쉬울 것 같다. 여기까진 내 생각일 뿐이고 또 다른 재미있는 주제가 있으면 들고오겠다 : )
3-1학기는 시험보랴 프로젝트하랴 정말 바빴었고 힘들었는데 지금보니 느낌이 또 색다르다! 역시 지나고보면 다 추억인가보다 !!(???)ㅋㅋㅋㅋㅋ
'직장생활 > Programming (C, Python)' 카테고리의 다른 글
[R 프로그래밍] R Studio 설치/다운로드 (0) | 2021.07.29 |
---|---|
[Jupyter notebook] PyCharm보다 편한 주피터 노트북 1분만에 설치하기 (0) | 2021.07.29 |
[TensorFlow] 튜토리얼 - Keras basic - Basic classification: Classify images of clothing (0) | 2021.07.29 |
[데이터마이닝] Titanic: Machine Learning from Disaster _ python (0) | 2021.07.29 |
[데이터마이닝] Linear Regression_Python (0) | 2021.07.29 |