데이터를 그냥 사용할 수 있으면 정말 좋겠지만 실제 데이터는 클린징을 거쳐야 분석에 사용될 수 있는 경우가 많습니다. 이번 시간에는 결측치와 이상치를 정제하는 방법을 알아보겠습니다.

1. 결측치 정제하기

결측치란 누락된 값, 비어 있는 값, NULL Data 를 의미합니다. 실제 데이터는 데이터 수집 과정에서 발생한 오류 등으로 인해 결측치가 포함되어 있는 경우가 많기 때문에 이 결측치를 정제하는 과정을 거쳐야만 함수 사용에 문제가 발생하지 않고 분석 결과에 왜곡이 없습니다.

 

 

Data Download

https://github.com/ark1st/Doit_R_ARKS_CODE/blob/master/sample_NoNA.csv

 

ark1st/Doit_R_ARKS_CODE

Do it R 학습 및 블로그 작성에 있어서 가공한 데이터와 코드를 업로드 하는 공간 입니다. - ark1st/Doit_R_ARKS_CODE

github.com

 

 

 

결측치 실습에는 mpg 데이터 중 class, cty, hwy만 뽑아 임의로 수정한 파일을 실습에 사용하겠습니다.

sample.csv를 다운로드 하여 불러오기 합니다.

mpg_sample <- read.csv("sample_NoNA.csv")

 

1.1. 결측치 확인하기

View(mpg_sample)로 데이터를 확인해 보니 빠진 데이터들이 존재 합니다. R에서는 결측치를 대문자 NA로 표시하는 것을 알 수 있습니다.

View(mpg_sample)

 

결측치를 정제하기 위해서는 결측치가 들어 있는지 확인해야 합니다. 결측치를 확인하기 위해서는 is.na()를 사용합니다. 혹은 is.na()table() 에 적용하면 데이터에 결측치가 몇 개 들어있는지 출력해 줍니다.

is.na(mpg_sample) #결측치 전체 출력 (결과는 생략)
table(is.na(mpg_sample)) #결측치 테이블 출력

## FALSE  TRUE 
##  689    13 

위 TRUE 빈도에서 13개의 결측치가 확인되었습니다.

 

결측치를 정제하기 위해서는 데이터 전체보다는 구체적으로 어느 변수에 결측치가 있는지 확인하는 것이 좋습니다. table(is.na()에 변수명까지 지정하면 해당하는 변수에 결측치가 몇 개 있는지 반환하여 줍니다.

table(is.na(mpg_sample$cty))

## FALSE  TRUE 
##  226     8 

cty 변수에는 결측치가 8개 있는 것으로 확인됩니다. 이때 이 결측치가 포함된 상태 그대로 함수를 적용하여 데이터 분석을 한다면 오류가 발생하거나 왜곡된 값이 출력됩니다.

av = mean(mpg_sample$cty)
av

## [1] NA 

 

1.2. 결측치 제거하기

결측치를 제거하기 위해서 filter()is.na()를 적용해 보겠습니다. cty 변수를 기준으로 결측치를 제거해 보겠습니다.

library(dyplr)
mpg_Nona <- mpg_sample %>% filter(!is.na(cty))

 

여러 변수 동시에 결측치를 제거하려면 논리 연산자 & 를 사용합니다.

mpg_Nona2 <- mpg_sample %>% filter(!is.na(cty) & is.na(hwy))

 


 

데이터 프레임 전체의 결측치를 제거해 주는 함수도 있습니다. na.omit()을 이용하면 변수를 지정하지 않고도 결측치가 있는 행을 제거할 수 있습니다.

mpg_noNa3 <- na.omit(mpg_sample)

 


함수에서 지원하는 파라미터를 활용해도 됩니다. 여러 함수들이 결측치를 제외하고 연산을 수행해 주는 기능을 가지고 있습니다. na.rmT로 설정하면 결측치를 제외하고 함수 연산을 수행합니다.

mean(mpg_sample, na.rm = 'T')

 


데이터가 큰 경우에는 결측치를 제거하고 분석해도 문제가 없습니다. 그러나 데이터가 작고 결측치가 많은 경우에는 결측치를 모두 제거하면 데이터가 손실되어 분석 결과가 왜곡됩니다. 그래서 결측치를 다른 값으로 대체하여 연산하기도 하는데 이것을 결측치 대체법이라고 합니다. 결측치를 대체할 때에는 평균이나 최빈값 등의 대표값을 대체하거나 결측치의 예측값을 추정하여 대체할 수 있습니다.

그러나 지금은 바로 결측치를 대체할 수 없습니다. 왜냐하면 지금의 데이터 상태로는 평균을 구하면 엄청난 왜곡이 있기 때문입니다.

 

2. 이상치 정제하기

mpg_sample 데이터를 확인해 보면 9999 등의 값이 들어 있는 것을 확인할 수 있습니다. 이렇듯 정상 범주에서 크게 벗어난 값을 이상치라고 합니다. 데이터를 수집할 때 오류가 발생하였거나 굉장히 드물게 극단적인 값이 나타날 수도 있습니다. 이러한 이상치가 포함되어 있으면 분석 결과가 왜곡되기 때문에 분석에 앞서 이상치를 제거해야 합니다.

 

2.1. 논리적으로 존재할 수 없는 경우

이 경우는 대부분 범주형 변수에서 볼 수 있는 경우입니다. 성별의 경우 남성은 1, 여성은 2로 설정 되어 있을 때 3이라는 값이 들어 있거나, 논리값 T, F로 결정된 경우에 이상한 값이 들어 있는 경우입니다. 혹은 연속형 변수에서 문자 값이 들어있다거나 하는 경우에도 논리적으로 존재할 수 없는 경우에 해당됩니다.

이 경우에는 table()로 이상치를 확인한 후에 ifelse() 를 사용하여 결측치로 바꾸어 줍니다.

data2 <- ifelse(data$sex == 3, NA, data$sex)

 

2.2. 극단적인 값

논리적으로 존재할 수는 있지만 극단적으로 크거나 작은 값을 극단치라고 합니다. 주로 연속형 변수에서 나타날 수 있습니다. 예를 들어 몸무게 변수에 200kg의 값이 들어 있다면 그것이 논리적으로 존재할 수는 있지만 너무 극단적인 값이기 때문에 분석 결과가 왜곡될 수도 있습니다.

이때에는 정상 범위를 판단하여 정상 범위에서 벗어나는 값을 삭제하여 극단치를 제거합니다. 이때 정상치를 선정하는 기준이 정말 중요합니다. 이 정상치를 선정할 때 납득할 만한 근거가 있어야 통계에는 신빙성이 생기기 때문입니다.

우리는 boxplot 그래프를 이용해서 중심에서 크게 벗어난 값을 극단치로 간주하고 제거하는 실습을 해 보겠습니다.

 

boxplot(mpg_sample$cty)

 

여기서 각 항목이 의미하는 내용입니다.

상자그림 설명
상자 아래 세로 점선 아랫수염 하위 0 ~ 25% 내에 해당하는 값
상자 밑면 1사분위수(Q1) 하위 25% 위치 값
상자 내 굵은 선 2사분위수(Q2) 하위 50% 위치 값(중앙값)
상자 윗면 3사분위수(Q3) 하위 75% 위치 값
상자 위 세로 점선 윗수염 하위 75 ~ 100%내에 해당하는 값
상자 밖 가로선 극단치 경계 Q1, Q3 밖 1.5 IQR 내 최댓값
상자 밖 점 표식 극단치 Q1, Q3 밖 1.5 IQR 내 벗어난 값

 

이때 이것을 수치값으로 확인하고 싶으면 함수 뒤에 $stats 를 삽입하면 됩니다.

boxplot(mpg_sample$cty)$stats
boxplot(mpg_sample$hwy)$stats

 

정상 범위를 파악한 후 이 범위를 벗어난 값을 결측 처리합니다.

mpg_sample$cty <- ifelse(mpg_sample$cty < 9 | mpg_sample$cty > 26, NA, mpg_sample$cty)
mpg_sample$hwy <- ifelse(mpg_sample$hwy < 9 | mpg_sample$hwy > 26, NA, mpg_sample$hwy)

 

다시 평균을 구해봅시다.

meancty <- mean(mpg_sample$cty)

 

1.3. 결측치 대체하기

결측치를 정상적인 평균값으로 대체할 수 있게 되었기 때문에 결측치를 대체하여 보겠습니다.

mpg_sample$cty <- ifelse(is.na(mpg_sample$cty),meancty, mpg_sample$cty)

 

 

Source Code

https://github.com/ark1st/Doit_R_ARKS_CODE/blob/master/NA_Outl

 

// 참고자료

김영우, 『쉽게 배우는 R 데이터 분석』, 이지스 퍼블리싱,

2019 이영호, "확률과통계" 가천대학교, 2019.03.21

'Programming > R' 카테고리의 다른 글

텍스트 마이닝 - KoNLP  (0) 2019.05.20
그래프 만들기  (0) 2019.04.30
데이터 전처리  (0) 2019.04.14
변수 조작하기  (0) 2019.04.10
데이터 파악하기  (0) 2019.04.09

+ Recent posts