데이터를 다루다 보면 결측값 즉, 비어있는 값을 보게 됩니다. 대부분의 실제 현장에서 수집하는 데이터들은 완전히 수집이 되지 않아 결측값이 존재합니다. 결측값은 수집시 오류가 발생하거나, 기록시 누락 또는 미응답 등 수집 과정에서 문제가 생겨 데이터의 공백이 생긴 경우 입니다. 대부분 결측값을 "NA"로 표시가 되며 도메인에 따라 -999, -99 등으로 표기가 되기도 합니다. 그럼 R에서 결측값을 찾는 방법에 대해 몇 가지 알아 보도록 하겠습니다.
먼저 R에서 결측값이 포함된 데이터를 불러 오겠습니다.결측값이 포함된 간단한 예제 데이터를 만들어서 사용해보도록 하겠습니다.
library(tidyverse)
> sample = tibble(var1 = c(1,10,100,NA,NA),
var2 = c(2, 20, 100,1000,10),
var3 = c(1, 60, 500,2000,60),
var4 = c("a",NA,NA,"d","c"))
sample
# A tibble: 5 x 4
var1 var2 var3 var4
<dbl> <dbl> <dbl> <chr>
1 1 2 1 a
2 10 20 60 NA
3 100 100 500 NA
4 NA 1000 2000 d
5 NA 10 60 c
1. colSums(is.na())
먼저, 결측값인지 아닌지를 TRUE, FALSE 논리값을 반환해주는 함수는 is.na()입니다. 해당 논리값을 사용하여 colSums() 함수를 사용하면 data.frame에서 모든 열의 결측값의 합을 알 수 있습니다.
> colSums(is.na(sample))
var1 var2 var3 var4
2 0 0 2
2. complete.cases()
해당함수는 결측값인지 아닌지 TRUE, FALSE로 반환해주는 함수 입니다. 이름에서 알 수 있듯이 complete.cases즉, 완전전한 경우만 TRUE로 출력합니다. 즉, 결측값이 아니면 TRUE, 결측값이면 FALSE를 반환합니다.
> complete.cases(sample)
[1] TRUE FALSE FALSE FALSE FALSE
TRUE는 결측값이 아닌 값, FALSE는 결측값이 들어가 있는 row입니다. complete.cases()를 사용해서 결측값이 들어가 있거나 혹은 들어가 있지 않은 row만 출력할 수 있습니다.
> sample[!complete.cases(sample),]
# A tibble: 4 x 4
var1 var2 var3 var4
<dbl> <dbl> <dbl> <chr>
1 10 20 60 NA
2 100 100 500 NA
3 NA 1000 2000 d
4 NA 10 60 c
위 코드와 같이 !complete.cases(sample)를 sample의 row값으로 넣어주면 됩니다. 여기서 "!"는 부정의 뜻입니다. 즉, 완전한 값이 아닌 결측값이 하나라도 들어어있는 모든 row를 출력하라는 의미 입니다.
3. filter
dplyr의 filter함수를 사용해서도 결측값을 찾을 수 있습니다. 해당 방법은 특정 column의 이름을 넣어서 해당 column의 결측값을 모두 반환하는 방법입니다. var1의 결측값을 모두 반환해보겠습니다.
> sample %>% filter(is.na(var1))
# A tibble: 2 x 4
var1 var2 var3 var4
<dbl> <dbl> <dbl> <chr>
1 NA 1000 2000 d
2 NA 10 60 c
var1에는 결측값이 총 2개가 들어가 있었습니다. var1의 결측값을 모두 반환하면서 그 결측값에 해당하는 다른 column들의 값도 반환하여 data.frame의 형태를 그대로 유지합니다.
4. filter_all, select_if
dplyr의 filter와 select는 그 용도가 다양합니다. 함수뒤에 _at, _all, _if를 붙여 다양하게 활용 할 수 있습니다. 해당 예제에서는 결측값을 찾는데 적용 해보도록 하겠습니다. 해다예제에서는 빠른 확인을 위해 간단한 예제 데이터를 만들어서 사용해보겠습니다.
먼저 select 입니다. select는 data.frame에서 원하는 column을 추출 할 때 사용하는 함수 입니다.
select_if() 함수는 특정 조건을 만족하는 column을 추출 할 때 사용합니다. select_if()와 any(), is.na() 함수를 함께 사용하면 "NA"가 들어있는 모든
column을 추출 할 수 있습니다. any()는 ()안의 조건중 하나라도 만족하는지 TRUE, FALSE로 반환해주는 함수 입니다.
> sample %>% select_if(~any(is.na(.))) # NA들어간 컬럼 추출
# A tibble: 5 x 2
var1 var4
<dbl> <chr>
1 1 a
2 10 NA
3 100 NA
4 NA d
5 NA c
sample 데이터에서 NA가 포함된 모든 column을 추출 하였습니다. ~any(is.na(.))에서 any()앞의 "~"와 is.na()안의 "."은 purrr sytle의 함수형 프로그래밍 표시 입니다. "~"은 함수를 뜻하고, "."은 앞의 data.frame의 모든 column을 뜻합니다. 해당 내용과 관련하여서는 purrr 패키지에 대한 내용을 다룰 때 자세히 설명하도록 하겠습니다.
다음은 filter 입니다. filter는 조건에 맞는 row를 추출해주는 함수입니다. filter_all을 사용하면 모든 column에 대해 결측값이 하나라도 들어있으면 해당 row를 추출할 수 있습니다. filter_all()함수는 특히, any_vars(), all_vars()함수와 같이 사용됩니다.
> sample %>% filter_all(any_vars(is.na(.)))
# A tibble: 4 x 4
var1 var2 var3 var4
<dbl> <dbl> <dbl> <chr>
1 10 20 60 NA
2 100 100 500 NA
3 NA 1000 2000 d
4 NA 10 60 c
코드를 해석하면, 모든 column에 대해 NA가 하나라도 들어가 있으면 해당 row를 추출하라는 함수 입니다.
몇 가지 NA를 추출하는 방법에 대해 알아보았습니다. 여러가지 방법이 있겠지만 해당 방법을 사용하면 우선은 빠르게 결측값을 파악 할 수 있으리라 생각합니다. 감사합니다.
'R' 카테고리의 다른 글
[dplyr] arrange, distinct, slice로 데이터 추출 및 정리 (0) | 2024.03.05 |
---|---|
[caret] caret을 활용한 머신러닝 모델 구축 (1) | 2023.08.07 |
[tidymodels] tidymodels를 활용한 머신러닝 모델 구축하기 (0) | 2023.07.31 |
[dplyr] select, filter, mutate, summarise로 데이터 다루기 (0) | 2023.07.26 |