|
이번에는 실제적인 데이타를 예로 들어 data cleaning, subsetting 및 변환을 살펴보고자 한다. L모 교수는 최근 환자들의 자료를 엑셀화일로 정리한 후 CSV화일로 변환하였다. 환자의 이름과 신상명세는 제외하였다. 전체 데이타에서 50명의 환자 데이타만 제시한 것이다.
data=read.csv("ECMO.csv")
head(data)
## Sex Age Year Holiday Insertion.time ECMO.duration Death Height Weight
## 1 1 49 2009 1 1 8 1 NA NA
## 2 1 77 2009 1 NA 24 0 NA NA
## 3 0 67 2009 1 1 15 0 NA NA
## 4 0 56 2010 1 0 5 0 1.65 68
## 5 0 67 2010 1 0 2 0 1.70 65
## 6 0 76 2010 1 0 5 0 1.64 68
## BMI Diagnosis Smoking CAD CVA PAD DM HBP Indication Mode CA OHCA
## 1 NA Myocarditis 2 1 1 1 1 1 0 0 1 NA
## 2 NA ACS 2 1 1 1 1 0 0 0 1 NA
## 3 NA ACS 0 0 1 1 0 0 0 0 0 1
## 4 29.76 ACS 2 1 1 1 1 0 0 0 0 1
## 5 26.37 ARDS 2 1 1 1 1 1 1 1 0 1
## 6 30.21 ACS 1 1 1 1 0 0 0 0 1 NA
## CPR.duration CA.ECMO.Time EKG Weaning Vent Intu.day HD ICU.stay CRRT
## 1 NA NA 2 0 0 8 30 11 0
## 2 NA NA 2 0 0 27 31 31 1
## 3 37 37 0 0 0 17 17 17 0
## 4 25 25 0 1 0 5 5 5 0
## 5 210 210 2 1 0 3 43 3 1
## 6 NA NA 2 0 0 9 12 12 1
## CRRT.duration CAG PCI GCS Bleeding Tamponade Pulmo AKI Liver.failure MOF
## 1 8 1 1 15 1 1 1 0 1 1
## 2 NA 0 1 5 1 1 1 0 1 1
## 3 13 0 0 3 1 1 0 0 1 0
## 4 3 0 0 3 1 1 1 0 1 1
## 5 NA 1 1 12 1 1 1 0 1 1
## 6 NA 0 0 4 1 1 1 1 1 0
## Sepsis Stroke Leg.ischemia WBC Hct PLT Sodium K Lactate PH HCO3
## 1 1 1 1 16400 43.0 248 143.2 3.9 10.6 7.20 15.9
## 2 1 1 1 5230 30.1 154 143.2 3.1 NA 7.49 22.0
## 3 1 1 1 9670 36.0 54 144.8 3.4 NA 7.26 9.0
## 4 1 1 1 10930 44.8 293 136.8 3.2 NA 7.18 13.4
## 5 0 1 1 17950 22.3 70 143.2 6.5 NA 7.14 10.9
## 6 1 1 1 6790 40.1 173 140.5 3.8 NA 7.29 14.9
## BUN Cr Glucose Albumin Total..bilirubin CRP D.dimer CK.MB Troponin
## 1 20.1 2.3 184 4.7 1.1 0.31 2.29 30.95 3.050
## 2 6.3 1.0 153 4.2 0.5 1.03 NA 3.97 0.298
## 3 20.1 1.5 56 2.2 0.5 13.34 1.03 8.91 0.088
## 4 15.9 1.5 200 2.5 0.6 0.07 NA 3.47 0.020
## 5 48.9 2.5 488 1.6 0.3 23.27 0.44 4.38 0.036
## 6 15.8 0.9 178 3.8 1.1 0.29 NA 17.70 0.674
## PRC FFP PC Cryo Survive
## 1 5 3 72 0 1
## 2 22 7 61 0 0
## 3 35 9 136 0 0
## 4 10 0 18 0 0
## 5 24 5 42 0 0
## 6 14 0 46 0 0
str(data)
## 'data.frame': 50 obs. of 65 variables:
## $ Sex : int 1 1 0 0 0 0 0 0 1 0 ...
## $ Age : int 49 77 67 56 67 76 48 67 69 38 ...
## $ Year : int 2009 2009 2009 2010 2010 2010 2010 2010 2010 2010 ...
## $ Holiday : int 1 1 1 1 1 1 1 1 1 1 ...
## $ Insertion.time : int 1 NA 1 0 0 0 1 1 0 0 ...
## $ ECMO.duration : int 8 24 15 5 2 5 1 14 6 1 ...
## $ Death : int 1 0 0 0 0 0 0 0 0 0 ...
## $ Height : num NA NA NA 1.65 1.7 1.64 1.75 1.65 1.55 1.7 ...
## $ Weight : num NA NA NA 68 65 68 75 60 53 65 ...
## $ BMI : num NA NA NA 29.8 26.4 ...
## $ Diagnosis : Factor w/ 8 levels "ACS","ARDS","LA myxoma",..: 4 1 1 1 2 1 1 1 1 4 ...
## $ Smoking : int 2 2 0 2 2 1 0 2 2 0 ...
## $ CAD : int 1 1 0 1 1 1 1 1 1 1 ...
## $ CVA : int 1 1 1 1 1 1 1 1 1 1 ...
## $ PAD : int 1 1 1 1 1 1 1 1 1 1 ...
## $ DM : int 1 1 0 1 1 0 0 0 0 1 ...
## $ HBP : int 1 0 0 0 1 0 0 0 1 1 ...
## $ Indication : int 0 0 0 0 1 0 0 0 0 0 ...
## $ Mode : int 0 0 0 0 1 0 0 0 0 0 ...
## $ CA : int 1 1 0 0 0 1 0 1 0 1 ...
## $ OHCA : int NA NA 1 1 1 NA 0 NA 0 NA ...
## $ CPR.duration : int NA NA 37 25 210 NA 30 NA 20 NA ...
## $ CA.ECMO.Time : int NA NA 37 25 210 NA 240 NA 540 NA ...
## $ EKG : int 2 2 0 0 2 2 2 2 2 2 ...
## $ Weaning : int 0 0 0 1 1 0 1 0 1 1 ...
## $ Vent : int 0 0 0 0 0 0 0 0 0 0 ...
## $ Intu.day : Factor w/ 23 levels "1","10","11",..: 21 12 7 18 13 22 9 8 19 1 ...
## $ HD : int 30 31 17 5 43 12 2 20 6 2 ...
## $ ICU.stay : int 11 31 17 5 3 12 2 20 6 2 ...
## $ CRRT : int 0 1 0 0 1 1 1 1 0 1 ...
## $ CRRT.duration : int 8 NA 13 3 NA NA NA NA 5 NA ...
## $ CAG : int 1 0 0 0 1 0 1 0 1 0 ...
## $ PCI : int 1 1 0 0 1 0 1 1 1 1 ...
## $ GCS : int 15 5 3 3 12 4 3 3 3 8 ...
## $ Bleeding : int 1 1 1 1 1 1 0 0 1 0 ...
## $ Tamponade : int 1 1 1 1 1 1 1 1 1 1 ...
## $ Pulmo : int 1 1 0 1 1 1 1 1 1 1 ...
## $ AKI : int 0 0 0 0 0 1 1 1 0 1 ...
## $ Liver.failure : int 1 1 1 1 1 1 1 1 1 1 ...
## $ MOF : int 1 1 0 1 1 0 0 0 1 1 ...
## $ Sepsis : int 1 1 1 1 0 1 1 0 1 1 ...
## $ Stroke : int 1 1 1 1 1 1 1 1 1 1 ...
## $ Leg.ischemia : int 1 1 1 1 1 1 1 1 1 1 ...
## $ WBC : int 16400 5230 9670 10930 17950 6790 20410 18230 21500 11910 ...
## $ Hct : num 43 30.1 36 44.8 22.3 40.1 32.1 26.5 30.2 41.7 ...
## $ PLT : int 248 154 54 293 70 173 203 334 235 308 ...
## $ Sodium : num 143 143 145 137 143 ...
## $ K : num 3.9 3.1 3.4 3.2 6.5 3.8 6.6 4.1 5.4 4.4 ...
## $ Lactate : num 10.6 NA NA NA NA NA 15.5 15.6 7.6 3.8 ...
## $ PH : num 7.2 7.49 7.26 7.18 7.14 ...
## $ HCO3 : num 15.9 22 9 13.4 10.9 14.9 10.5 12.7 12.5 16.7 ...
## $ BUN : num 20.1 6.3 20.1 15.9 48.9 15.8 54.6 49.9 40.7 32 ...
## $ Cr : num 2.3 1 1.5 1.5 2.5 0.9 3.9 1.3 1.6 1.7 ...
## $ Glucose : int 184 153 56 200 488 178 256 230 208 131 ...
## $ Albumin : num 4.7 4.2 2.2 2.5 1.6 3.8 3 4.1 2.8 3.9 ...
## $ Total..bilirubin: num 1.1 0.5 0.5 0.6 0.3 1.1 0.6 0.5 1 0.6 ...
## $ CRP : num 0.31 1.03 13.34 0.07 23.27 ...
## $ D.dimer : num 2.29 NA 1.03 NA 0.44 NA NA 4.97 NA NA ...
## $ CK.MB : num 30.95 3.97 8.91 3.47 4.38 ...
## $ Troponin : num 3.05 0.298 0.088 0.02 0.036 ...
## $ PRC : int 5 22 35 10 24 14 9 42 10 3 ...
## $ FFP : int 3 7 9 0 5 0 0 5 0 0 ...
## $ PC : int 72 61 136 18 42 46 0 170 54 0 ...
## $ Cryo : int 0 0 0 0 0 0 0 0 0 0 ...
## $ Survive : int 1 0 0 0 0 0 0 0 0 0 ...
데이타는 모두 50 예이며 65개의 변수로 되어있다. 이중 대부분의 변수는 Yes,No의 범주형 변수이나 Excel에서 0,1로 입력하여 모두 numeric 변수로 되어 있다. 성별은 여자는 1, 남자는 0으로 코딩했고 착오로 인해 Yes/No로 표현해야 하는 여러 변수는 No를 1로, Yes를 0으로 입력했다고 한다. 먼저 남여의 경우는 다음과 같이 바꾸었다.
data$Sex=ifelse(data$Sex==1,"Female","Male")
Yes/No가 아닌 데이타는 다음과 같이 ifelse를 이용해 바꾸었다.
data$Insertion.time=ifelse(data$Insertion.time==1,"Emergency","Elective")
data$Death=ifelse(data$Death==1,"Survivor","Non-survivor")
data$Indication=ifelse(data$Indication==1,"Respiratory","Cardiology")
data$Mode=ifelse(data$Mode==1,"VV","VA")
data$OHCA=ifelse(data$OHCA==1,"IHCA","OHCA")
data$EKG=ifelse(data$EKG==0,"Asystole",
ifelse(data$EKG==1,"PEA","ETC"))
data$Weaning=ifelse(data$Weaning==1,"Fail","Success")
head(data)
## Sex Age Year Holiday Insertion.time ECMO.duration Death Height
## 1 Female 49 2009 1 Emergency 8 Survivor NA
## 2 Female 77 2009 1 <NA> 24 Non-survivor NA
## 3 Male 67 2009 1 Emergency 15 Non-survivor NA
## 4 Male 56 2010 1 Elective 5 Non-survivor 1.65
## 5 Male 67 2010 1 Elective 2 Non-survivor 1.70
## 6 Male 76 2010 1 Elective 5 Non-survivor 1.64
## Weight BMI Diagnosis Smoking CAD CVA PAD DM HBP Indication Mode CA
## 1 NA NA Myocarditis 2 1 1 1 1 1 Cardiology VA 1
## 2 NA NA ACS 2 1 1 1 1 0 Cardiology VA 1
## 3 NA NA ACS 0 0 1 1 0 0 Cardiology VA 0
## 4 68 29.76 ACS 2 1 1 1 1 0 Cardiology VA 0
## 5 65 26.37 ARDS 2 1 1 1 1 1 Respiratory VV 0
## 6 68 30.21 ACS 1 1 1 1 0 0 Cardiology VA 1
## OHCA CPR.duration CA.ECMO.Time EKG Weaning Vent Intu.day HD
## 1 <NA> NA NA ETC Success 0 8 30
## 2 <NA> NA NA ETC Success 0 27 31
## 3 IHCA 37 37 Asystole Success 0 17 17
## 4 IHCA 25 25 Asystole Fail 0 5 5
## 5 IHCA 210 210 ETC Fail 0 3 43
## 6 <NA> NA NA ETC Success 0 9 12
## ICU.stay CRRT CRRT.duration CAG PCI GCS Bleeding Tamponade Pulmo AKI
## 1 11 0 8 1 1 15 1 1 1 0
## 2 31 1 NA 0 1 5 1 1 1 0
## 3 17 0 13 0 0 3 1 1 0 0
## 4 5 0 3 0 0 3 1 1 1 0
## 5 3 1 NA 1 1 12 1 1 1 0
## 6 12 1 NA 0 0 4 1 1 1 1
## Liver.failure MOF Sepsis Stroke Leg.ischemia WBC Hct PLT Sodium K
## 1 1 1 1 1 1 16400 43.0 248 143.2 3.9
## 2 1 1 1 1 1 5230 30.1 154 143.2 3.1
## 3 1 0 1 1 1 9670 36.0 54 144.8 3.4
## 4 1 1 1 1 1 10930 44.8 293 136.8 3.2
## 5 1 1 0 1 1 17950 22.3 70 143.2 6.5
## 6 1 0 1 1 1 6790 40.1 173 140.5 3.8
## Lactate PH HCO3 BUN Cr Glucose Albumin Total..bilirubin CRP
## 1 10.6 7.20 15.9 20.1 2.3 184 4.7 1.1 0.31
## 2 NA 7.49 22.0 6.3 1.0 153 4.2 0.5 1.03
## 3 NA 7.26 9.0 20.1 1.5 56 2.2 0.5 13.34
## 4 NA 7.18 13.4 15.9 1.5 200 2.5 0.6 0.07
## 5 NA 7.14 10.9 48.9 2.5 488 1.6 0.3 23.27
## 6 NA 7.29 14.9 15.8 0.9 178 3.8 1.1 0.29
## D.dimer CK.MB Troponin PRC FFP PC Cryo Survive
## 1 2.29 30.95 3.050 5 3 72 0 1
## 2 NA 3.97 0.298 22 7 61 0 0
## 3 1.03 8.91 0.088 35 9 136 0 0
## 4 NA 3.47 0.020 10 0 18 0 0
## 5 0.44 4.38 0.036 24 5 42 0 0
## 6 NA 17.70 0.674 14 0 46 0 0
남은 데이타 중 0/1로 코딩한 열은 모두 Yes/No로 바꾸고 싶다. 일일이 코딩하는 방법은 다음과 같다. 바꿔야 하는 자료중 일부를 제시하면 다음과 같다.
data$Holiday=ifelse(data$Holiday==1,"No","Yes")
data$Smoking=ifelse(data$Smoking==1,"No","Yes")
data$CAD=ifelse(data$CAD==1,"No","Yes")
data$CVA=ifelse(data$CVA==1,"No","Yes")
data$PAD=ifelse(data$PAD==1,"No","Yes")
data$DM=ifelse(data$DM==1,"No","Yes")
data$HBP=ifelse(data$HBP==1,"No","Yes")
data$CA=ifelse(data$CA==1,"No","Yes")
data$Vent=ifelse(data$Vent==1,"No","Yes")
data$CRRT=ifelse(data$CRRT==1,"No","Yes")
data$CAG=ifelse(data$CAG==1,"No","Yes")
data$PCI=ifelse(data$PCI==1,"No","Yes")
data$Bleeding=ifelse(data$Bleeding==1,"No","Yes")
data$Tamponade=ifelse(data$Tamponade==1,"No","Yes")
data$Pulmo=ifelse(data$Pulmo==1,"No","Yes")
data$AKI=ifelse(data$AKI==1,"No","Yes")
data$Liver.failure=ifelse(data$Liver.failure==1,"No","Yes")
data$MOF=ifelse(data$MOF==1,"No","Yes")
data$Sepsis=ifelse(data$Sepsis==1,"No","Yes")
data$Stroke=ifelse(data$Stroke==1,"No","Yes")
data$Leg.ischemia=ifelse(data$Leg.ischemia==1,"No","Yes")
물론 이정도는 감당할 수 있다. 21개 정도의 열은 일일이 위와 같이 코드를 복사해서 고칠 수 있다. 하지만 자료가 65개의 변수가 아닌 650개의 변수라면? 거의 불가능하거나 포기하고 싶어질 것이다.
여기서 잠깐 생각해보자. 지금 우리가 하고 싶은 일은 무엇인가? 첫째, 전체 자료 중에 0,1로 코딩되어있는 열을 찾아낸다. 둘째, 그 열에 포함되어 있는 자료에서 0을 “Yes”로 1을 “No”로 바꿔준다.
이 두가지 단계를 거치면 우리가 원하는 자료를 얻을수 있을 것이다. 이번 문제는 1단계 2단계 모두 functional programming이다. funtional이란 함수들 중에서 인수로써 함수를 받아들이고 output으로 벡터를 반환하는 함수로서 apply 류의 함수가 대표적이다. 힌트는 1,2단계 모두 lapply를 사용하여 한줄로 코딩할수 있다는 것이다.
통계분석에 드는 시간과 노력은 data cleaning에 70%, 분석에 30%라는 얘기가 있다. 이 문제를 해결할 수 있으면 데이타 cleaning에 자신을 가질수 있을 것이다.
모두들 응모하세요. 정답을 맞추신 보든 분께는 제가 출간예정인 책을 한권씩 선물로 드립니다. 제가 올린 글 중 Functional programming 부분을 잘 읽고 이해한다면 쉽게 풀수 있을 겁니다. 정답은 한가지가 아니라 여러가지가 있을수 있읍니다. 실제 코딩을 해보고 다른 사람의 코드와 비교해보는 것이 실력 향상의 지름길입니다.
이 통계에 필요한 ECMO.csv자료를 다운하여 코드를 작성한 후 정답을 올려주세요.
첫댓글 재밌네요! 역시 문제를 풀어봐야 실력이 느네요.
재밌는 문제 올려주셔서 감사합니다 :)
isCategorical <- function(col, type=c(0,1)){
lvl <- levels(factor(col))
if(all(lvl %in% type))
return(TRUE)
else
return(FALSE)
}
result <- lapply(data, function(col){
if(isCategorical(col, c(0,1))){
col[col==0] <- "Yes"
col[col==1] <- "No"
}
return(col)
})
result <- as.data.frame(result)
head(result)
str(result)
틀렸다면 조언 부탁드립니다!
틀리지는 않으셨구요 조언입니다.
1. isCategorical 함수는 한줄로 줄일수 있읍니다.
isCategorical <- function(x) all(unique(x) %in% c(0,1))
# all 함수 자체가 TRUE, FALSE를 반환합니다. 따라서 if else는 필요없읍니다.
# levels(factor(x)) 대신 unique(x) 가 더 간단해 보입니다.
2. 이부분은 ifelse함수를 쓰면 좋을듯합니다. 개인취향이지만요
col[col==0] <- "Yes"
col[col==1] <- "No"
이부분을 col=ifelse(col==0,"Yes","No")
3. 함수 첫부분에 명시적으로 쓸때 말고는 보통 return(col) 말고 col을 쓰는 것이 보통입니다.
@cardiomoon 오 정말이네요! 감사합니다 !!
음 그렇게 해도 되는군요. 또 다른 분은요?