일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- Apple
- RS-485
- 파이썬
- 월패드
- 국내주식
- Python
- 미국주식
- SK텔레콤
- Bestin
- matter
- Espressif
- cluster
- ConnectedHomeIP
- homebridge
- 애플
- 매터
- 힐스테이트 광교산
- 공모주
- 오블완
- 나스닥
- esp32
- MQTT
- 코스피
- 홈네트워크
- 배당
- raspberry pi
- 해외주식
- 티스토리챌린지
- Home Assistant
- 현대통신
- Today
- Total
YOGYUI
R NA 처리하기 (with dplyr) 본문
R에서는 데이터셋의 NA를 대체(Imputation)하는 여러가지 방법을 제공한다
(ex: DMwR 패키지의 centralImputation)
본 포스트에서는 dplyr 패키지를 활용해서 데이터셋에 NA가 있는지 파악하고, NA값들을 대체하는 방법에 대해 알아보도록 한다
1. 데이터 준비
mtcars 데이터셋의 일부 속성을 임의로 NA로 만들어보자
set.seed(1234)
# load dataset
df <- mtcars
# sample index
idx1 <- sample(1:nrow(df), 4)
idx2 <- sample(1:nrow(df), 6)
# replace 'drat' attribute to NA
df$drat[idx1] <- NA
# replace 'qsec' attribute to NA
df$qsec[idx2] <- NA
idx1
> [1] 28 16 26 22
idx2
> [1] 5 12 15 9 32 6
summary(df)
> mpg cyl disp hp drat wt qsec vs am gear carb
Min. :10.40 Min. :4.000 Min. : 71.1 Min. : 52.0 Min. :2.760 Min. :1.513 Min. :14.50 Min. :0.0000 Min. :0.0000 Min. :3.000 Min. :1.000
1st Qu.:15.43 1st Qu.:4.000 1st Qu.:120.8 1st Qu.: 96.5 1st Qu.:3.132 1st Qu.:2.581 1st Qu.:16.74 1st Qu.:0.0000 1st Qu.:0.0000 1st Qu.:3.000 1st Qu.:2.000
Median :19.20 Median :6.000 Median :196.3 Median :123.0 Median :3.695 Median :3.325 Median :17.51 Median :0.0000 Median :0.0000 Median :4.000 Median :2.000
Mean :20.09 Mean :6.188 Mean :230.7 Mean :146.7 Mean :3.624 Mean :3.217 Mean :17.58 Mean :0.4375 Mean :0.4062 Mean :3.688 Mean :2.812
3rd Qu.:22.80 3rd Qu.:8.000 3rd Qu.:326.0 3rd Qu.:180.0 3rd Qu.:3.920 3rd Qu.:3.610 3rd Qu.:18.83 3rd Qu.:1.0000 3rd Qu.:1.0000 3rd Qu.:4.000 3rd Qu.:4.000
Max. :33.90 Max. :8.000 Max. :472.0 Max. :335.0 Max. :4.930 Max. :5.424 Max. :20.01 Max. :1.0000 Max. :1.0000 Max. :5.000 Max. :8.000
NA's :4 NA's :6
(16, 22, 26, 28)번째 레코드의 drat 속성값을 NA로, (5, 6, 9, 12, 15, 32)번째 레코드의 qsec 속성값을 NA로 대체했다
2. NA 속성 찾기
위에서 본것처럼 summary 함수를 활용하면 NA가 존재하는지 쉽게 파악할 수 있다
dplyr 패키지를 사용해서 NA 속성을 찾아보자
library(dplyr)
df_na <- df %>%
select_if(function(x) any(is.na(x)))
select_if 구문과 is.na 함수를 활용해 NA값이 존재하는 속성만 추출할 수 있다
(any 함수를 통해 레코드 1개라도 NA값이 존재하면 해당 속성이 선택됨)
summary(df_na)
> drat qsec
Min. :2.760 Min. :14.50
1st Qu.:3.132 1st Qu.:16.74
Median :3.695 Median :17.51
Mean :3.624 Mean :17.58
3rd Qu.:3.920 3rd Qu.:18.83
Max. :4.930 Max. :20.01
NA's :4 NA's :6
names(df_na)
> [1] "drat" "qsec"
complete.cases 함수를 활용한 다음 구문과 동일한 동작
(complete.cases: NA인 속성이 모두 없는 레코드에 대해서만 TRUE 반환)
df_na <- df[!complete.cases(df),]
dplyr summarise_each 구문을 활용해 각 속성별 NA의 개수를 구할 수 있다
df_na %>%
summarise_each(funs(sum(is.na(.))))
>
drat qsec
1 4 6
※ summarise_each와 funs 구문은 deprecated되었다는 경고메시지가 뜬다 (0.7, 0.8 버전 이후)
다음과 같이 최신 문법(lambda 활용)으로 구현해도 결과는 동일하다
df_na %>%
summarise_all(list(~ sum(is.na(.))))
3. NA값 대체하기
(1) 0으로 대체하기
df %>%
select_if(function(x) any(is.na(x))) %>%
replace(is.na(.), 0)
> drat qsec
Mazda RX4 3.90 16.46
Mazda RX4 Wag 3.90 17.02
Datsun 710 3.85 18.61
Hornet 4 Drive 3.08 19.44
Hornet Sportabout 3.15 0.00
Valiant 2.76 0.00
Duster 360 3.21 15.84
Merc 240D 3.69 20.00
Merc 230 3.92 0.00
Merc 280 3.92 18.30
Merc 280C 3.92 18.90
Merc 450SE 3.07 0.00
Merc 450SL 3.07 17.60
Merc 450SLC 3.07 18.00
Cadillac Fleetwood 2.93 0.00
Lincoln Continental 0.00 17.82
Chrysler Imperial 3.23 17.42
Fiat 128 4.08 19.47
Honda Civic 4.93 18.52
Toyota Corolla 4.22 19.90
Toyota Corona 3.70 20.01
Dodge Challenger 0.00 16.87
AMC Javelin 3.15 17.30
Camaro Z28 3.73 15.41
Pontiac Firebird 3.08 17.05
Fiat X1-9 0.00 18.90
Porsche 914-2 4.43 16.70
Lotus Europa 0.00 16.90
Ford Pantera L 4.22 14.50
Ferrari Dino 3.62 15.50
Maserati Bora 3.54 14.60
Volvo 142E 4.11 0.00
select_if문은 굳이 없어도 무방하다
다음 구문과 동일한 동작을 한다
df$drat[is.na(df$drat)] <- 0
df$qsec[is.na(df$qsec)] <- 0
(2) 평균값으로 대체하기
mutate와 replace 구문 활용
평균 구하기: mean(x, na.rm = TRUE)
df %>%
select_if(function(x) any(is.na(x))) %>%
mutate(drat = replace(drat, is.na(drat), mean(drat, na.rm = TRUE))) %>%
mutate(qsec = replace(qsec, is.na(qsec), mean(qsec, na.rm = TRUE)))
> drat qsec
1 3.900000 16.46000
2 3.900000 17.02000
3 3.850000 18.61000
4 3.080000 19.44000
5 3.150000 17.57846
6 2.760000 17.57846
7 3.210000 15.84000
8 3.690000 20.00000
9 3.920000 17.57846
10 3.920000 18.30000
11 3.920000 18.90000
12 3.070000 17.57846
13 3.070000 17.60000
14 3.070000 18.00000
15 2.930000 17.57846
16 3.624286 17.82000
17 3.230000 17.42000
18 4.080000 19.47000
19 4.930000 18.52000
20 4.220000 19.90000
21 3.700000 20.01000
22 3.624286 16.87000
23 3.150000 17.30000
24 3.730000 15.41000
25 3.080000 17.05000
26 3.624286 18.90000
27 4.430000 16.70000
28 3.624286 16.90000
29 4.220000 14.50000
30 3.620000 15.50000
31 3.540000 14.60000
32 4.110000 17.57846
위와 같이 열 이름을 하나하나 붙여가는 것도 나쁘지 않은 방법인데, dplyr 고수라면 속성도 한번에 묶어서 함수처리하면 될듯하다 (난 잘 모르겠다 ㅎㅎ)
다음 구문과 동일 동작
df$drat[is.na(df$drat)] <- mean(df$drat, na.rm = TRUE)
df$qsec[is.na(df$qsec)] <- mean(df$qsec, na.rm = TRUE)
(3) 중앙값으로 대체하기
평균값 대체하기 구문에서 mean 대신 median 사용하면 된다
df %>%
select_if(function(x) any(is.na(x))) %>%
mutate(drat = replace(drat, is.na(drat), median(drat, na.rm = TRUE))) %>%
mutate(qsec = replace(qsec, is.na(qsec), median(qsec, na.rm = TRUE)))
> drat qsec
1 3.900 16.46
2 3.900 17.02
3 3.850 18.61
4 3.080 19.44
5 3.150 17.51
6 2.760 17.51
7 3.210 15.84
8 3.690 20.00
9 3.920 17.51
10 3.920 18.30
11 3.920 18.90
12 3.070 17.51
13 3.070 17.60
14 3.070 18.00
15 2.930 17.51
16 3.695 17.82
17 3.230 17.42
18 4.080 19.47
19 4.930 18.52
20 4.220 19.90
21 3.700 20.01
22 3.695 16.87
23 3.150 17.30
24 3.730 15.41
25 3.080 17.05
26 3.695 18.90
27 4.430 16.70
28 3.695 16.90
29 4.220 14.50
30 3.620 15.50
31 3.540 14.60
32 4.110 17.51
'Software > R' 카테고리의 다른 글
R caret::preProcess - 수치형 데이터 정규화, 표준화 (0) | 2021.06.17 |
---|---|
R 회귀분석 모델 성능판단 - RMSE, MAE, R squared (0) | 2021.06.16 |
R pROC 패키지::ROC 커브 그리기, AUC 메트릭 계산하기 (0) | 2021.06.15 |
R 스크립트 파일 경로 가져오기 (0) | 2021.06.05 |
R 작업 경로(working directory, wd) Set/Get (0) | 2021.06.05 |