728x90
반응형
R 기본 함수로 결측값 다루기
0. 결측값을 다뤄볼 test Dataset을 만들어보자.
# test Dataset
row_number = 20
ID_vt = seq(1, row_number)
ID_vt = paste0("A", ID_vt)
math_vt = sample(10:100, row_number)
english_vt = sample(10:100, row_number)
science_vt = sample(10:100, row_number)
korean_vt = sample(10:100, row_number)
df = data.frame(ID = ID_vt, math = math_vt, english = english_vt,
science = science_vt, korean = korean_vt)
df[c(10,16), c("math")] = NA
df[c(4,6,10,19), c("english")] = NA
df[c(10,20), c("science")] = NA
df[c(4,15,16,20), c("korean")] = NA
df
## ID math english science korean
## 1 A1 66 94 78 53
## 2 A2 89 87 74 82
## 3 A3 36 58 44 60
## 4 A4 96 NA 21 NA
## 5 A5 37 96 63 19
## 6 A6 63 NA 45 94
## 7 A7 80 14 79 20
## 8 A8 75 19 56 66
## 9 A9 35 44 59 14
## 10 A10 NA NA NA 35
## 11 A11 72 92 27 39
## 12 A12 74 79 96 76
## 13 A13 98 80 10 10
## 14 A14 11 28 87 62
## 15 A15 44 90 20 NA
## 16 A16 NA 24 35 NA
## 17 A17 88 12 55 22
## 18 A18 58 25 40 81
## 19 A19 67 NA 48 25
## 20 A20 50 75 NA NA
- 무작위 위치에 결측값을 넣어주었다.
1. 결측값 확인하기
함수 | 의미 |
is.na(x) | data에 속한 NA를 True로 나타낸다. |
na.fail(x) | dasta에 NA가 포함되어 있으면 Error를 반환한다. |
na.omit(x) | data에 NA가 포함되어 있으면 이를 제외한다. |
na.pass(x) | data에 NA가 포함되어 있더라도 무시하고 진행한다. |
complete.case(x) | data에서 결측값이 없는 행만 반환한다. |
- is.na() 함수와 table() 함수를 혼합해서 사용해보면 보다 재밌는 결과가 나온다.
# 데이터 전체를 NA 기준으로 TRUE, FALSE를 반환
is.na(df)
## ID math english science korean
## [1,] FALSE FALSE FALSE FALSE FALSE
## [2,] FALSE FALSE FALSE FALSE FALSE
## [3,] FALSE FALSE FALSE FALSE FALSE
## [4,] FALSE FALSE TRUE FALSE TRUE
## [5,] FALSE FALSE FALSE FALSE FALSE
## [6,] FALSE FALSE TRUE FALSE FALSE
## [7,] FALSE FALSE FALSE FALSE FALSE
## [8,] FALSE FALSE FALSE FALSE FALSE
## [9,] FALSE FALSE FALSE FALSE FALSE
## [10,] FALSE TRUE TRUE TRUE FALSE
## [11,] FALSE FALSE FALSE FALSE FALSE
## [12,] FALSE FALSE FALSE FALSE FALSE
## [13,] FALSE FALSE FALSE FALSE FALSE
## [14,] FALSE FALSE FALSE FALSE FALSE
## [15,] FALSE FALSE FALSE FALSE TRUE
## [16,] FALSE TRUE FALSE FALSE TRUE
## [17,] FALSE FALSE FALSE FALSE FALSE
## [18,] FALSE FALSE FALSE FALSE FALSE
## [19,] FALSE FALSE TRUE FALSE FALSE
## [20,] FALSE FALSE FALSE TRUE TRUE
- 전체 Data 안에서 결측값 여부를 보여준다.
# 데이터 내, 다수 변수들의 결측값을 한 번에 확인
# 출력된 결과는 각 변수별 결측값의 수이다.
colSums(is.na(df))
## ID math english science korean
## 0 2 4 2 4
- 가장 쉬운 코드로 결측값의 상태를 보여준다.
# 데이터 내 총 결측값의 수
table(is.na(df))
## FALSE TRUE
## 88 12
sum(is.na(df))
## [1] 12
- 둘 모두 총 결측값의 수이다.
# 특정 열의 결측치 확인
table(is.na(df$math))
## FALSE TRUE
## 18 2
- 특정 열에서 결측값이 몇 개 있는지 반환한다.
# 결측값이 전체 데이터 셋에서 차지하는 비중
mean(is.na(df))
## [1] 0.12
- 전체 데이터에서 결측값이 차지하는 비중으로 dataframe$column을 하여 특정 컬럼에 대해서만 확인할 수도 있다.
2. 결측값이 있는 행 제거하기
- 데이터 내에서 결측값이 있는 모든 행을 제거하는 방법과 변수별 결측값이 있는 행만 취사 선택하여 제거하는 방법이 있다.
- 전체 결측값을 제거하는 경우는 아래와 같다.
# 결측치가 없는 행만 반환1
na.omit(df)
## ID math english science korean
## 1 A1 55 15 63 52
## 2 A2 79 73 95 21
## 3 A3 33 84 66 49
## 5 A5 15 35 78 91
## 7 A7 80 45 67 100
## 8 A8 91 34 97 84
## 9 A9 85 51 61 23
## 11 A11 63 65 43 88
## 12 A12 13 83 32 12
## 13 A13 99 39 69 64
## 14 A14 76 46 83 96
## 17 A17 11 80 31 33
## 18 A18 68 92 12 24
# 결측치가 없는 행만 반환2
df[complete.cases(df),]
## ID math english science korean
## 1 A1 47 94 37 54
## 2 A2 61 62 25 94
## 3 A3 96 40 83 49
## 5 A5 63 81 11 43
## 7 A7 90 41 85 88
## 8 A8 70 30 49 19
## 9 A9 97 84 90 22
## 11 A11 80 76 52 14
## 12 A12 84 22 41 66
## 13 A13 16 58 93 61
## 14 A14 75 21 30 45
## 17 A17 51 56 55 71
## 18 A18 37 53 84 33
- na.omit()과 complete.cases()는 유사한 기능을 한다.
- 특정 변수의 결측값만 제거하는 방법은 다음과 같다.
# math 컬럼의 결측값을 제외하고 가져오자
df %>% filter(!is.na(math))
## ID math english science korean
## 1 A1 15 36 69 12
## 2 A2 94 100 74 58
## 3 A3 71 94 32 62
## 4 A4 93 NA 34 NA
## 5 A5 48 58 46 52
## 6 A6 64 NA 92 77
## 7 A7 40 16 72 40
## 8 A8 86 86 77 19
## 9 A9 81 89 28 63
## 10 A11 47 91 94 93
## 11 A12 97 27 45 70
## 12 A13 14 63 62 59
## 13 A14 61 72 50 49
## 14 A15 92 30 65 NA
## 15 A17 78 78 13 44
## 16 A18 68 99 15 86
## 17 A19 30 NA 68 48
## 18 A20 72 66 NA NA
- dplyr은 R에서 기본으로 제공하는 함수는 아니지만, Data Handling에서 필수인 함수이므로 한번 짚고 넘어가겠다.
df[complete.cases(df[,"math"]),]
## ID math english science korean
## 1 A1 15 36 69 12
## 2 A2 94 100 74 58
## 3 A3 71 94 32 62
## 4 A4 93 NA 34 NA
## 5 A5 48 58 46 52
## 6 A6 64 NA 92 77
## 7 A7 40 16 72 40
## 8 A8 86 86 77 19
## 9 A9 81 89 28 63
## 11 A11 47 91 94 93
## 12 A12 97 27 45 70
## 13 A13 14 63 62 59
## 14 A14 61 72 50 49
## 15 A15 92 30 65 NA
## 17 A17 78 78 13 44
## 18 A18 68 99 15 86
## 19 A19 30 NA 68 48
## 20 A20 72 66 NA NA
- na.omit()처럼 모든 결측값을 한번에 제거하는 방법은, 분석에서 중요하지 않은 변수의 결측값의 존재로 인해 실제 사라지지 않아도 되는 결측값까지 모두 제거해버릴 위험이 있다.
- 그러므로, na.omit()과 같은 결측값 제거 방법을 사용하기 전에 분석 대상이 될 변수와 표본 축소가 필요한 경우(예를 들어 비흡연자만 대상으로 하여 흡연 관련 변수와 흡연자를 분석 대상에서 제외함) 이를 먼저 실시하여 Data를 1차 정리하고 결측값 제거를 하도록 하자.
3. 결측값이 있는 열의 연산
- 결측값이 데이터에 포함돼 있는 경우, 이를 바로 연산하면 결과가 NA로 출력된다.
- 결측값이 있는 행을 제외하고 연산하고자 한다면 na.rm 파라미터에 True로 전달하면 된다.
# math 열에 있는 결측값만 제외하고 가져와보자
mean(df$math, na.rm = TRUE)
## [1] 60.44444
# math 컬럼의 결측값을 제외하고 mean을 계산해보자
library(dplyr)
df %>% summarise(mean_N = mean(math, na.rm = TRUE))
## [1] 60.44444
- 결측값을 다룰 때 가장 중요한 것은 분석 대상 집단을 정하는 것으로, 분석 목표에 필요한 변수를 모두 가져오며, 결측값이 존재하지 않는 대상 집단을 명확히 해야한다.
- 이 부분은 초보 분석가들이 하기 가장 좋은 실수 중 하나로 변수 A의 결측값과 변수 B의 결측값이 서로 다르게 제거된 상태에서 평균을 비롯한 각종 연산 값을 도출하면, 서로 다른 집단에 대한 연산값이 도출되는 결과가 나올 수 있다.
- 그러므로, na.rm 인자를 이용해 연산하기보다는 분석 대상 집단을 명확히 하여 결측값을 모두 제거한 후 연산하기를 바란다.
지금까지 R의 기본 함수를 이용해서 결측값을 다루는 법에 대해 학습해보았다. 다음 포스트에서는 결측값을 다루는 데 있어서 가장 유용한 라이브러리 중 하나인 naniar 패키지를 활용해서 결측값을 다루는 법을 알아보자.
728x90
반응형
'분석에 필요한 배경 지식 > 결측값' 카테고리의 다른 글
결측값: 3.1. R-결측값 다루기(2) (0) | 2021.02.12 |
---|---|
결측값: 2.1. 결측값 대체(2) - Multiple Imputation (0) | 2021.01.21 |
결측값: 2.0 결측값 대체(1) - Single imputation (4) | 2021.01.21 |
결측값: 1.1 기본개념(2) - 결측값의 종류 (0) | 2021.01.20 |
결측값: 1.0 기본개념(1) - 결측값이 미치는 영향 (0) | 2021.01.20 |