1. 시험에 나왔습니다
ADP 실기 시험을 보았는데 결측치 처리 문제(https://it-freelancer.tistory.com/293)가 첫 부분에 나왔습니다.
그렇게 어려운 문제가 아니었음에도, 제한 시간 내에 만족스런 답을 제출하지 못하고 허둥댄 것 같습니다.
2. 결론부터 말하자면, 다음에는 이렇게 해야겠습다.
# 결측값 확인
library(skimr)
library(dplyr)
data(Cars93,package="MASS")
Cars93 %>%
skim() %>%
filter(n_missing > 0)
# 최빈값 중위수 대치
Cars93 <- randomForest::na.roughfix(Cars93)
3. 결측치 처리 방법
결측치 처리에는 여러 가지 방법이 있습니다.
Wiki 를 찾아보면 크게는 단순 대치 다중 대치가 있고, 단순 대치에는 핫덱 콜드덱 그리고 블라블라 있습니다.
2 Single imputation
2.1 Hot-deck
2.2 Cold-deck
2.3 Mean substitution
2.4 Non-negative matrix factorization
2.5 Regression
3 Multiple imputation
출처 : https://en.wikipedia.org/wiki/Imputation_(statistics)#Mean_substitution
randomForest 패키지에서 제공하는 Rough Imputation 도 있습니다.
Impute Missing Values by median/mode.
na.roughfix: Rough Imputation of Missing Values
출처 : https://www.rdocumentation.org/packages/randomForest/versions/4.7-1.1/topics/na.roughfix
중위수와 최빈값은 대푯값이라는 측면에서는 평균과 비슷한 성격입니다.그래서 평균대체법의 한가지 방법이라고 할 수도 있을 것 같습니다. 그렇지만, Mean substitution 의 Mean 이 평균값이므로 median/mode 를 이용하는 Rough Imputation 과 동일하다고 확신할 수가 없네요. wiki 자료에 median/mode 에 대한 언급이 없어 아쉽습니다.
4. R script 연구
# 결측치 대체 - 연속형 중위수 대치 (간단한 데이터셋)
# 변수 개수가 적은 경우 눈으로 확인해서 한 땀 한 땀 코딩하면 됩니다.
#------------------------------------------------------------------
airquality
summary(airquality) # Ozone 37 Solar.R 7 - Median : 31.50 Median :205.0
airquality.clean <- airquality
airquality.clean$Ozone <- ifelse(is.na(airquality.clean$Ozone),
31.50,
airquality.clean$Ozone)
airquality.clean$Solar.R <- ifelse(is.na(airquality.clean$Solar.R),
205.0,
airquality.clean$Solar.R)
summary(airquality.clean) # 결측치 없어지고, 중위수는 그대로 있음
# 결측치 대체 - 범주형의 최빈값 대치
# 가장 많은 범주를 table 함수로 일일이 확인해서...
#------------------------------------------------------------------
ToothGrowth
summary(ToothGrowth) #원본에는 결측이 없습니다.
ToothGrowth.noise <- ToothGrowth
#연습을 위해 첫 번째 라인에 결측치를 강제로 만들기
str(ToothGrowth)
rownames(ToothGrowth)
ToothGrowth.noise[,1:3]
ToothGrowth.noise$supp <- ifelse(rownames(ToothGrowth)==1,
NA,
ToothGrowth.noise$supp)
summary(ToothGrowth.noise)
# 1,2 가 30 개씩이었는데 1행 VC(2) 하나를 NA 로 만드니 30개 29개입니다
table(ToothGrowth.noise$supp) # 1 이 30개
ToothGrowth.clean <- ToothGrowth.noise
ToothGrowth.clean$supp <- ifelse(is.na(ToothGrowth.clean$supp),
1,
ToothGrowth.clean$supp)
summary(ToothGrowth.clean)
table(ToothGrowth.clean$supp)
# table 로 최빈값 확인해서 ifelse 이용해서 대치하는 거 노가다군요
# 변수가 많은 (변수 27개) 케이스에서는
#------------------------------------------------------------------
data(Cars93,package="MASS")
str(Cars93)
sum(is.na(Cars93)) #결측치 13 있음.
summary(Cars93) # 눈으로 못찾을 것은 아니지만...
apply(is.na(Cars93),2,sum) # 조금 낫긴 하지만 역시 눈이 아픔
library(dplyr)
apply(is.na(Cars93),2,sum) %>%
data.frame() %>%
filter(.>0) # 이런 식으로 사용하는 것이 맞는 것인가?
library(skimr)
skim(Cars93)
Cars93 %>%
skim() %>%
filter(n_missing > 0) # 저는 이 방식이 맘에 들었습니다.
# roughfix 전후 비교를 위해 확인해 둡니다.
sum(Cars93$Rear.seat.room) #NA 가 있을때 sum 하면 NA 가 되는군요
sum(Cars93$Rear.seat.room,na.rm = T) #2532.5
median(Cars93$Rear.seat.room,na.rm = T) #27.5
Cars93.clean <- Cars93
library(randomForest)
# 할당을 해주면 된다.
Cars93.clean <- na.roughfix(Cars93.clean)
# 중위수는 그대로고 합은 NA 가 중위수로 바뀐만큼 증가했습니다.
sum(Cars93.clean$Rear.seat.room,na.rm = T) #2587.5 <- 2532.5 + 2*27.5
median(Cars93.clean$Rear.seat.room,na.rm = T) #27.5
참고한 자료들
https://en.wikipedia.org/wiki/Imputation_(statistics)#Mean_substitution
https://www.rdocumentation.org/packages/randomForest/versions/4.7-1.1/topics/na.roughfix
https://terms.naver.com/entry.naver?docId=3434283&cid=58456&categoryId=58456
'ADP (R)' 카테고리의 다른 글
[R] 로지스틱 회귀 연습 (with mtcars) (0) | 2022.10.26 |
---|---|
[R] 다변량 데이터 상관관계 분석 (0) | 2022.10.23 |
[R] kernlab class probability calculations failed (0) | 2022.10.23 |
[R] prediction from a rank-deficient fit may be misleading (0) | 2022.10.23 |
[R] 칼럼별로 결측값 갯수 구하기 (0) | 2022.10.17 |