// 1. 페이지의 에서 최대한 위에 이 코드를 붙여넣으세요. // 아래의 메타 태그를 복사해 사이트 홈페이지의 섹션에 붙여 넣어주세요. //2. 여는 태그 바로 뒤에 코드를 붙여넣으세요.

새소식

반응형
AI/인공지능 당뇨병 관련 예측(diabetes 130)

Diabetes 130 US hospitals for years 1999-2008 / 당뇨병 환자가 30일 이내에 병원을 재방문 할 것인지에 대한 인공지능 예측(1)

  • -
반응형

데이터 다운로드 링크

https://www.kaggle.com/brandao/diabetes

 

Diabetes 130 US hospitals for years 1999-2008

Diabetes - readmission

www.kaggle.com

 

diabetes 130데이터는 미국 130 개 병원 및 통합 전달 네트워크에서 10년간의(1999-2008) 임상 치료를 나타냅니다.
여기에는 환자 및 병원 결과를 나타내는 50 개 이상의 변수가 포함되어 있습니다.
다음 기준을 충족하는 환자에 대한 정보가 데이터로 추출되었습니다.

- 입원 환자의 만남 입니다.
- 당뇨병 환자의 당뇨병 진단으로 시스템에 입력되었습니다.
- 체류 기간은 최소 1 , 최대 14 일이었습니다.
- 만남 중에 실험실 테스트가 수행되었습니다.
- 만남 중에 약물이 투여되었습니다.

 

이번 글에서는 데이터 탐색과 데이터 전처리를 다루겠습니다.

 

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import pandasModule as pdm

자주 쓰는 함수를 pandasModule이라는 클래스로 미리 만들어 놓았습니다.

먼저 데이터를 불러오고 정보를 살펴봅니다.

 

pdm = pdm.pandasModule
df = pd.read_csv('./data/diabetic_data.csv')
df.info()

각 컬럼에 대한 정보 입니다. 컬럼에서 y값을 정하는게 중요한데 저는 readmitted를 y 컬럼으로 정했으며
30일 이내에 재방문할 예측 모델을 구현하려 합니다.

환자가 일부 병원에서 재입 원할 것인지 아는 것이 중요합니다. 그 이유는 재 입원을 피하기 위해 치료법을 변경할 수 있기 때문입니다.

 - encounter_id : 고유 식별자
 - patient_nbr : 환자의 고유 식별 번호
 - race : 인종
 - gender : 남성, 여성 및 알 수 없음 / 무효
 - age : 10 년 간격으로 그룹화 된 연령 : 0, 10), 10, 20),…, 90, 100)
 - weight : 무게 (파운드)
 - admission_type_id : 9 개의 고유 값에 해당하는 정수 식별자 (예 : 긴급, 긴급, 선택, 신생아 및 사용할 수 없음)
 - discharge_disposition_id : 퇴원 처리 29 개의 고유 값에 해당하는 정수 식별자 (예 : 집으로 퇴원, 만료 및 사용할 수 없음)
 - admission_source_id : 21 개의 고유 한 값에 해당하는 정수 식별자 (예 : 의사 소개, 응급실 및 병원에서 전송)
 - time_in_hospital : 입원과 퇴원 사이의 정수 일수
 - payer_code : 23 개의 고유 값에 해당하는 정수 식별자 (예 : Blue Cross / Blue Shield, Medicare 및 자기 부담 의료)
 - medical_specialty : 입원 의사의 전문 분야에 대한 정수 식별자 (예 : 심장학, 내과, 가족 / 일반 진료, 외과의)
 - num_lab_procedures : 실험실 절차 수 만남 중 수행 된 실험실 테스트 수
 - num_procedures : 절차 수 숫자 만남 중 수행 된 절차 (실험실 테스트 제외)의 수
 - num_medications : 투약 횟수 만남 중 투여 된 고유 한 일반 이름의 수
 - number_outpatient : 외래 방문 횟수 만남 전 해에 환자의 외래 방문 횟수
 - number_emergency : 응급 방문 횟수 만남 전 1 년 동안 환자의 응급 방문 횟수
 - number_inpatient : 입원 환자 방문수 만남 전년도에 환자의 입원 환자 방문수
 - diag_1 : 1 차 진단 (ICD9의 처음 세 자리로 코딩 됨); 848 개의 고유 값
 - diag_2 : 이차 진단 (ICD9의 처음 세 자리로 코딩 됨); 923 개의 고유 값
 - diag_3 : 추가 이차 진단 (ICD9의 처음 세 자리로 코딩 됨); 954 개의 고유 값
 - number_diagnoses : 진단 수 시스템에 입력 된 진단 수 0 %
 - max_glu_serum : 포도당 혈청 검사 결과 결과의 범위 또는 검사를받지 않았는지 여부를 나타냅니다.
                   값 : "> 200", "> 300", "normal"및 측정되지 않은 경우 "none"

 * A1C 검사는 지난 2 ~ 3 개월 동안 혈중 포도당 평균 수치를 측정하는 혈액 검사입니다.
   이 검사는 당뇨병 환자에게 혈당치가 얼마나 잘 조절되는지를 확인하는 데 사용되며 당뇨병 진단에 사용될 수 있습니다 .

 - A1Cresult : A1c 테스트 결과 결과의 범위 또는 테스트가 수행되지 않았는지 여부를 나타냅니다.
               값 : 결과가 8 %보다 크면 "> 8", 결과가 7 %보다 크지 만 8 %보다 작 으면 "> 7",
                    결과가 7 %보다 작 으면 "normal", 다음의 경우 "none" 측정되지 않았습니다.

 - 약물에 대한 24 가지 기능 일반 이름 : 메트포르민, 레파 글리 니드, 나테 글리 니드, 클로르 프로 파 미드, 글리메피리드, 아세토 헥사 미드, 글 리피 지드, 글리 부 리드, 톨 부타 미드, 피오글리타존, 로시글리타존, 아카보스, 미글 리톨, 트로글리타존, 톨 라자 미드, 글 리피 지드, 시타 글 립틴, 인슐린, 글 리피 지드 -metformin, glimepiride- pioglitazone, metformin-rosiglitazone 및 metformin-pioglitazone,이 기능은 약물이 처방되었는지 또는 복용량이 변경되었는지 여부를 나타냅니다.

 

값 : 만남 중에 용량이 증가하면 "up", 용량이 감소하면 "down", 용량이 변경되지 않은 경우 "steady", 약물이 처방되지 않은 경우 "no"

metformin, repaglinide, nateglinide, chlorpropamide, glimepiride, acetohexamide, glipizide
glyburide, tolbutamide, pioglitazone, rosiglitazone, acarbose, miglitol, troglitazone
tolazamide, examide, citoglipton, insulin, glyburide-metformin, glipizide-metformin
glimepiride-pioglitazone, metformin-rosiglitazone, metformin-pioglitazone


change : 당뇨병 약물 (용량 또는 일반 이름)이 변경되었는지 여부를 나타냅니다. 값 : "변경"및 "변경 없음"
diabetesMed : 처방 된 당뇨병 약이 있는지 여부를 나타냅니다. 값 : "예"및 "아니요"

 

 

각 컬럼에 대한 고유값들과 고유값들의 갯수를 파악해봅니다.

 

pdm.showUniqueInfos(df)

이렇게 각 컬럼에 대한 고유값들을 한눈에 볼 수 있습니다.

 

우선 데이터에서 결측치가 많거나 학습에 도움이 안되거나 심각한 불균형한 데이터들 삭제부터 시작합니다.

    encounter_id : 학습에 도움 안되는 고유값 입니다.
    patient_nbr : 마찬가지로 학습에 도움 안되는 고유값 입니다.
    weight : ? 값이 심각하게 많아서 삭제합니다.
    admission_type_id : 마찬가지로 학습에 도움 안되는 고유값 입니다.
    discharge_disposition_id : 마찬가지로 학습에 도움 안되는 고유값 입니다.
    admission_source_id : 마찬가지로 학습에 도움 안되는 고유값 입니다.
    payer_code : 마찬가지로 학습에 도움 안되는 고유값 입니다.
    medical_specialty : ?값이 심각하게 많고 변수가 가진 의미가 학습에 도움이 되질 않아 삭제 합니다.

    Number of medications : Number of distinct generic names administered during the encounter
    번역하면 만남 중 관리되는 고유 한 일반 이름의 수 입니다.
    num_medications : 정확한 정보는 잘 모르겠으나 마찬가지로 학습에 도움 안되는 고유값으로 판단하였습니다.

    다음 컬럼 삭제 목록은 Steady threshold 값을 100이하이면 삭제 하는것으로 정했습니다.

    #########acetohexamide#########
    No        101765
    Steady         1
    acetohexamide : 위와 같이 데이터가 심각하게 불균형하며 Steady가 100넘지 않습니다.

    #########tolbutamide#########
    No        101743
    Steady        23
    tolbutamide : 위와 같이 데이터가 심각하게 불균형하며 Steady가 100넘지 않습니다.

    #########troglitazone#########
    No        101763
    Steady         3
    troglitazone : 위와 같이 데이터가 심각하게 불균형하며 Steady가 100넘지 않습니다.

    #########tolazamide#########
    No        101727
    Steady        38
    Up             1
    tolazamide : 위와 같이 데이터가 심각하게 불균형하며 Steady가 100넘지 않습니다.

    #########examide#########
    No    101766
    examide : 위와 같이 데이터가 심각하게 불균형하며 Steady가 100넘지 않습니다.

    #########citoglipton#########
    No    101766
    citoglipton : 위와 같이 데이터가 심각하게 불균형하며 Steady가 100넘지 않습니다.

    #########glipizide-metformin#########
    No        101753
    Steady        13
    glipizideMetformin : 위와 같이 데이터가 심각하게 불균형하며 Steady가 100넘지 않습니다.

    #########glimepiride-pioglitazone#########
    No        101765
    Steady         1
    glimepiridePioglitazone : 위와 같이 데이터가 심각하게 불균형하며 Steady가 100넘지 않습니다.

    #########metformin-rosiglitazone#########
    No        101764
    Steady         2
    metforminRosiglitazone : 위와 같이 데이터가 심각하게 불균형하며 Steady가 100넘지 않습니다.

    #########metformin-pioglitazone#########
    No        101765
    Steady         1
    metforminPioglitazone : 위와 같이 데이터가 심각하게 불균형하며 Steady가 100넘지 않습니다.

이렇게 쓰지 않을 컬럼들을 삭제해줍니다.

 

df = pdm.dropColum(df, [
    encounter_id,
    patient_nbr,
    weight,
    admission_type_id,
    discharge_disposition_id,
    admission_source_id,
    payer_code,
    medical_specialty,
    num_medications,
    acetohexamide,
    tolbutamide,
    troglitazone,
    tolazamide,
    examide,
    citoglipton,
    glipizideMetformin,
    glimepiridePioglitazone,
    metforminRosiglitazone,
    metforminPioglitazone
])

 

삭제하고 데이터를 확인 합니다.

이제 쓰지 않을 컬럼들은 삭제했고 각 변수의 값들에 문제되는 값들을 제거해줍니다. 데이터의 갯수가 충분하지
않다면 삭제하기 보다는 값을 적절하게 채워주겠지만 데이터가 10만개나 되므로 데이터를 제거해도 무방하겠습니다.

먼저 race에서 ? 값을 가진 row들을 제거해 줍니다. 2273개의 row를 제거합니다.
그리고 gender에서 Unknown/Invalid 값을 가진 row를 제거합니다. 3개 밖에 안됩니다.

 

pdm.showUniqueInfos(df)
df.info()

pdm.deleteRow(df, race, '?')

pdm.deleteRow(df, gender, "Unknown/Invalid")

 

 

그리고 고유값이 유난히 많던 diag_1~3의 컬럼들 고유값을 찍어봅니다.

df['diag_1'].unique()

살펴보면 ? 값들이 있는데 문제 되는 값들이라 그냥 다 지워주고 확인해봅니다.

pdm.deleteRow(df, 'diag_1', '?')
pdm.deleteRow(df, 'diag_2', '?')
pdm.deleteRow(df, 'diag_3', '?')

df['diag_1'].unique()
df['diag_2'].unique()
df['diag_3'].unique()

결측치도 확인해봅니다.
결측치를 확인해보니 존재하지 않습니다.

df.isnull().sum()

 

데이터 갯수 확인해보면 31개의 컬럼에 98052개의 데이터가 남았습니다. 학습하기에 충분합니다.

df.shape

 

 

중복 데이터 제거후 한번 더 확인해 봅니다.

df.drop_duplicates()
df.shape

 

이제 못쓰거나 안쓰는 컬럼과 로우를 다 제거 하였고 학습을 위해 데이터들을 모두 수치형으로
변환 시켜줍니다.

*주의*
참고로 수치형으로 바꿀때 남자와 여자처럼 binary한 변수는 0과 1로 바꾸어도 괜찮으나
수치가 연속형이지 않은 명목형 변수는 수치로 바로 바꾸어서는 안됩니다. 나이 같은 경우는
연속형 변수이므로 수치로 바꾸어도 무방하겠습니다.

*중요*
그리고 y컬럼인 readmitted 변수는 우리가 예측할 '<30' 30일이내에 병원을 재방문한값은 1로
나머지는 0으로 바꾸어 줍니다.

# 성별을 숫자로 식별하도록 바꾸기
changeGenderValueDict = {
    'Male': 1,
    'Female': 0,
}
changeValueDict = {
    'No': 0,
    'Ch': 1,
}
changeDiabetesMedValueDict = {
    'No': 0,
    'Yes': 1,
}
# 나이를 숫자로 식별하도록 바꾸기
changeAgeValueDict = {
    '[0-10)': 0,
    '[10-20)': 1,
    '[20-30)': 2,
    '[30-40)': 3,
    '[40-50)': 4,
    '[50-60)': 5,
    '[60-70)': 6,
    '[70-80)': 7,
    '[80-90)': 8,
    '[90-100)': 9,
}
changeReadmittedValueDict = {
    'NO': 0,
    '>30': 0,
    '<30': 1
}

df = df.replace({'gender': changeGenderValueDict})
df = df.replace({'change': changeValueDict})
df = df.replace({'diabetesMed': changeDiabetesMedValueDict})
df = df.replace({'age': changeAgeValueDict})
df = df.replace({'readmitted': changeReadmittedValueDict})

데이터들을 수치형으로 바꾸고 다시한번 고유값과 갯수를 찍어봅니다.

pdm.showUniqueInfos(df)

이제 유난히 고유값이 많던 diag_1~3의 컬럼들을 전처리 해줍니다. 이 변수의 값들은 ICD-9의 값이며
ICD-9의 조건에 맞게 각 값들을 병명으로 바꾸어 줍니다.

 

# ICD - 9 코드 001-139의 목록 :infection 감염 및 기생 질환
# ICD - 9 코드 140-239의 목록 :tumor 종양
# ICD - 9 코드 240-279의 목록 :incretion 내분비, 영양 및 대사 질환, 그리고 면역 장애
# ICD - 9 코드 280-289의 목록 :blood 혈액 및 혈액 형성 기관의 질병
# ICD - 9 코드 290-319의 목록 :psychopathy 정신 질환
# ICD - 9 코드 320-359의 목록 :nerve 신경 계통의 질병
# ICD - 9 코드 360-389의 목록 :sensorial 감각 기관의 질병
# ICD - 9 코드 390-459의 목록 :circulatory 순환기 질병
# ICD - 9 코드 460-519의 목록 :breath 호흡 체계의 질병
# ICD - 9 코드 520-579의 목록 :digestive 소화기 계통의 질병
# ICD - 9 코드 580-629의 목록 :genitourinary 시스템의 질병
# ICD - 9 코드 630-676의 목록 :puerperium 임신 중 합병증 출산, 그리고 puerperium
# ICD - 9 코드 680-709의 목록 :skin 피부와 피하 조직의 질환
# ICD - 9 코드 710-739의 목록 :musculoskeletal 시스템 및 연결어의 질병 조직
# ICD - 9 코드 740-759의 목록 :inborn 선천적인 이상 현상
# ICD - 9 코드 760-779의 목록 :perinatal (출산 전후의) 특정 조건 perinatal 시대의 원산지
# ICD - 9 코드 780-799의 목록 :symptoms 증상, 징후, 그리고 병에 정의된 조건
# ICD - 9 코드 800-999의 목록 :poison 부상 및 중독
# ICD - 9 코드 목록 E와 V 코드 :injury 부상과 보완의 외부 원인 구분

def transferDiags(inputString):
    val = ''
    if inputString.isdigit():
        if 1 <= float(inputString) <= 139:
            val = "infection"
        elif 140 <= float(inputString) <= 239:
            val = "tumor"
        elif 240 <= float(inputString) <= 279:
            val = "incretion"
        elif 280 <= float(inputString) <= 289:
            val = "blood"
        elif 290 <= float(inputString) <= 319:
            val = "psychopathy"
        elif 320 <= float(inputString) <= 359:
            val = "nerve"
        elif 360 <= float(inputString) <= 389:
            val = "sensorial"
        elif 390 <= float(inputString) <= 459:
            val = "circulatory"
        elif 460 <= float(inputString) <= 519:
            val = "breath"
        elif 520 <= float(inputString) <= 579:
            val = "digestive"
        elif 580 <= float(inputString) <= 629:
            val = "genitourinary"
        elif 630 <= float(inputString) <= 679:
            val = "puerperium"
        elif 680 <= float(inputString) <= 709:
            val = "skin"
        elif 710 <= float(inputString) <= 739:
            val = "musculoskeletal"
        elif 740 <= float(inputString) <= 759:
            val = "inborn"
        elif 760 <= float(inputString) <= 779:
            val = "perinatal"
        elif 780 <= float(inputString) <= 799:
            val = "symptoms"
        elif 800 <= float(inputString) <= 999:
            val = "poison"
    else:
        if '.' in inputString:
            val = "diabetes"
        else:
            val = "injury"
    return val


# apply메소드의 lambda 함수는 공백까지 지우기 위해 사용한 코드입니다.
# 이렇게 중복으로도 사용 가능합니다.
df[diag_1] = df[diag_1].fillna("NONE")
df[diag_1] = df[diag_1].apply(transferDiags).apply(lambda x: x.replace(" ", ""))
df[diag_1].value_counts()

df[diag_1].unique()

df[diag_2] = df[diag_2].fillna("NONE")
df[diag_2] = df[diag_2].apply(transferDiags).apply(lambda x: x.replace(" ", ""))
df[diag_2].value_counts()
df[diag_2].unique()

df[diag_3] = df[diag_3].fillna("NONE")
df[diag_3] = df[diag_3].apply(transferDiags).apply(lambda x: x.replace(" ", ""))
df[diag_3].value_counts()
df[diag_3].unique()

각 diag 컬럼들 값을 병명으로 바꾸고 다시 한번 고유값들을 살펴보면 잘 바꾸어진것을 알 수 있습니다.

pdm.showUniqueInfos(df)

이제 명목형 변수들을 one hot encoding해줍니다.

명목현 변수는 0, 1, 2로 바꾸면 0, 1인 이진형변수는 괜찮지만 0,1,2,3,~ 이렇게 바꾸면 학습할때 숫자 사이에
관련이 없음에도 관련이 있게 학습되고 그래프가 보여지기 때문에 명목형은 one hot encoding 해주어야 합니다.

예를 들어 국가라는 변수명이 있고 고유값들이 러시아, 코리아, 재팬, 아메리카 이렇게 있다면
변수를 고유값의 갯수만큼 생성하여야 합니다.
ex) 해당 로우가 러시아인이면
   러시아 | 코리아 | 재팬
       1           0         0

이런식으로 해줘야합니다. one hot encoding은 판다스의 get_dummies 함수로 쉽게 할 수 있습니다.

###########################################
############ ONE HOT ENCODING #############
###########################################
# 명목형 변수들은 one hot encoding을 해준다.
df = pd.get_dummies(df, columns=[
    race,
    max_glu_serum,
    diag_1,
    diag_2,
    diag_3,
    A1Cresult,
    metformin,
    repaglinide,
    nateglinide,
    chlorpropamide,
    glimepiride,
    glipizide,
    glyburide,
    pioglitazone,
    rosiglitazone,
    acarbose,
    miglitol,
    insulin,
    glyburideMetformin
])

one hot encoding을 해주고 다시 고유값들을 찍어보면 잘 바뀐것을 볼 수 있습니다.

pdm.showUniqueInfos(df)

 

이제 아웃라이어를 제거합니다. 아웃라이어란 데이터 상의 다른 값들의 분포와 비교했을때 비정상적으로 떨어져있는 관측치입니다.

예를들어 마라톤 대회 데이터가 있다고 하면 보통 사람들이 2시간에서 2시간 30분 사이에 다 완주를 하는데 대회에 그냥 참가
목적으로 온 사람들은 4시간, 5시간 뒤에 완주를 한 경우의 데이터 입니다.

일반적인 데이터가 아니기 때문에 학습에 도움이 안되므로 제거해 줍니다.

아웃라이어는 명목형 변수에는 의미가 없고 순서형, 연속형 등 수치적인 의미가 있는 변수에 해당됩니다.
time_in_hospital : 병원에 머문 시간을 의미하므로 연속적인 의미가 있습니다.
num_lab_procedures : 실험실 절차 수 만남 중 수행 된 실험실 테스트 수이므로 연속적인 의미가 있습니다.
number_diagnoses : 진단 횟수를 의미하므로 연속적인 의미가 있습니다.

다만 현재 y의 값인 readmitted의 데이터가 균형적이지 않습니다. 1의 값이 0의 값에 비해 많이 모자라여
1을 최대한 살립니다. 따라서 아웃라이어 값을 포함하여도 readmitted가 1이면 지우지 않습니다.

mean : 평균
std : 표준편차
threshold : 임계값

임계값(Threshold)
애매한 값을 이분법으로 확실히 분류를 할 기준이 바로 임계값(Threshold)라고 합니다.
로지스틱 회귀 값을 이진 카테고리에 매핑(Mapping)하려면 분류 임계값(Classification Threshold, 결정 임계값이라고도 함)을 정의해야 합니다.
임계값보다 높은 값은 'true'를 나타내고 임계값보다 낮은 값은 'false'로 나타냅니다.
분류 임계값은 항상 0.5여야 한다고 생각하기 쉽지만 임계값은 문제에 따라 달라지므로 값을 조정해야 합니다.

 

###########################################
############# Outlier Remove ##############
###########################################
cols = df.columns

# time_in_hospital
# num_lab_procedures
# number_diagnoses

print(df.shape)
print("before drop outlier : {}".format(df.shape))

mean = df[time_in_hospital].mean()
std = df[time_in_hospital].std()
threshold = mean + 3 * std
nOutlier = np.sum(df[time_in_hospital] > threshold)
#len(np.where((df.time_in_hospital > threshold)  (df.readmitted != 1)))
drop_idx = df[(df.time_in_hospital > threshold) & (df.readmitted != 1)].index
print(df.shape)
print(df.drop(drop_idx, axis=0, inplace=True))
print(df[readmitted].value_counts())

mean = df[num_lab_procedures].mean()
std = df[num_lab_procedures].std()
threshold = mean + 3 * std
nOutlier = np.sum(df[num_lab_procedures] > threshold)
#len(np.where((df.time_in_hospital > threshold)  (df.readmitted != 1)))
drop_idx = df[(df.num_lab_procedures > threshold) & (df.readmitted != 1)].index
print(df.shape)
print(df.drop(drop_idx, axis=0, inplace=True))
print(df[readmitted].value_counts())

mean = df[number_diagnoses].mean()
std = df[number_diagnoses].std()
threshold = mean + 3 * std
nOutlier = np.sum(df[number_diagnoses] > threshold)
#len(np.where((df.time_in_hospital > threshold)  (df.readmitted != 1)))
drop_idx = df[(df.number_diagnoses > threshold) & (df.readmitted != 1)].index
print(df.shape)
print(df.drop(drop_idx, axis=0, inplace=True))
print(df[readmitted].value_counts())

df.dropna()
print("after drop outlier : {}".format(df.shape))

 

아웃라이어를 제거하여 데이터의 갯수가 97085개가 되었습니다. 1000개정도 제거 됐습니다.
y의 1인 값은 그데로 보존하였습니다.

print(df[readmitted].value_counts())

위에선 상한 아웃라이어를 제거했습니다. 이제 하한아웃라이어도 제거해줍니다.

print("before drop outlier : {}".format(df.shape))

def showLowerOutlier(df, stdev=3, show_total=False):
    # lower bound outliers
    cols = df.columns
    print(df.shape)
    for col in cols:
        mean = df[col].mean()
        std = df[col].std()
        threshold = mean - stdev * std
        n_outlier = np.sum(df[col] < threshold)
        print(col + ". mean : " + str(round(mean, 3)) + ", num of outlier : " + str(n_outlier))
        if (show_total == True) & (n_outlier != 0):
            print(df.loc[(df[col] < threshold), col][:5])
            df.drop(df[df[col] < threshold].index[:], inplace=True)

showLowerOutlier(df, show_total=True)
print("after drop outlier : {}".format(df.shape))

이렇게 전처리가 끝나고 box plot을 한번 찍어봅니다.

# box plot 한번에 찍기
cols = df.columns
for col in cols:
    if (col != "readmitted"):
        sns.boxplot(x="readmitted", y=str(col), data=df)
        plt.show()

 

데이터에서 X와 y를 분리 시킵니다

#- Scaling -
스케일링은 예를들어 집값의 범위는 100억~천만원 단위인데 BMI 값은 18~30이라 모델링할때 수치가 큰쪽으로 치우쳐
모델링이 잘 안되는것을 방지하기위해 설정한 범위 내의 값으로 변환 시켜줍니다. scaling model로는 StandardScaler를 씁니다.

fit_transform()은 fit() 과 transform() 함께 수행하는 메소드 입니다.

 

from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

X = df.loc[:, df.columns != readmitted]
y = df.loc[:, df.columns == readmitted]

scaler = StandardScaler()
X_Scaled = scaler.fit_transform(X)

여기까지 데이터 탐색 및 전처리를 마치고 시각화한것을 훑어보았습니다. 다음글에 모델학습과 결과를 보고 성능평가를 하겠습니다.

 

자세한 코드는 여기서 확인하실 수 있습니다. 감사합니다.

https://github.com/imtelloper/data-analysis-diabetes130

반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.