12.3 결측치의 처리
R에서 누락된 값은 NA
(not available) 기호로 표시됩니다. 불가능한 값(예 : 0으로 나누기)은 기호 NaN (Not a Number)로 표시됩니다. R은 문자 및 숫자 데이터에 동일한 기호를 사용합니다.
결측치의 처리는 여러 가지 방법이 있습니다. 여기서는 결측치를 다른 값으로 대체하는 방법과 결측치를 제외시키는 방법에 대하여 살펴보겠습니다.
결측치를 처리하기 전에 데이터 세트에 결측치가 있는지 확인하는 방법 먼저 학습하겠습니다.
12.3.1 결측치 확인
is.na()
함수를 이용하여 결측치를 확인할 수 있습니다. 또한 which()
함수와 결합하여 NA
가 있는 위치를 확인할 수 있으며, sum()
함수와 mean()
함수와 결합하여 NA
의 갯수와 NA
의 비율을 구할 수도 있습니다.
## 결측치가 있는 데이터 프레임에서 NA값을 확인합니다.
is.na(df) # df의 데이터 요소별로 NA이면 TRUE를 반환합니다.
## name gender myvar1 myvar2
## [1,] FALSE FALSE FALSE FALSE
## [2,] FALSE FALSE TRUE FALSE
## [3,] FALSE FALSE FALSE FALSE
# 데이터 프레임은 사작형 모양으로 is.na() 함수는
# "논리형 행렬/배열형"으로 반환합니다.
## 데이터 프레임의 특정 컬럼(벡터)에 NA가 있는지 확인합니다.
is.na(df$myvar1) # 논리형 벡터를 반환합니다.
## [1] FALSE TRUE FALSE
## 결측치가 있는 벡터에서 NA값을 확인합니다.
<- c(1,2,3,NA)
y is.na(y) # 논리형 벡터 (F F F T)를 반환합니다.
## [1] FALSE FALSE FALSE TRUE
## which(is.na()) 함수를 이용하여 NA가 있는 색인 번호를 확인할 수 있습니다.
which(is.na(df)) # 열 우선에 의한 요소의 위치인 8을 출력됩니다.
## [1] 8
which(is.na(y)) # 4를 출력합니다.
## [1] 4
## sum(is.na()) 함수를 이용하여 NA의 갯수를 확인할 수 있습니다.
sum(is.na(df)) # 1을 출력합니다.
## [1] 1
sum(is.na(y)) # 1을 출력합니다.
## [1] 1
## mean(is.na()) 함수를 이용하여 NA의 비율을 구할 수 있습니다.
mean(is.na(df)) # 1/12인 0.0833을 출력합니다.
## [1] 0.08333333
mean(is.na(y)) # 1/4인 0.25를 출력합니다.
## [1] 0.25
12.3.1.1 일반 데이터를 결측치 NA
로 변경하기
데이터 프레임에 NA
로 입력이 되어 있지 않은 데이터를 NA
로도 변경할 수 있습니다. 예를 들어, my.df
데이터 프레임의 myvar1
열에 있는99
의 값을 NA
로 변경하고, myvar2
열에 있는7
의 값을 NA
로 변경해 보겠습니다.
# my.df 데이터 프레임을 생성합니다.
<- data.frame(name = c("Kim", "Lee", "Park", "Choi", "Suh"),
my.df gender = c("Female", "Male", "Female", "Male", "Female"),
myvar1 = c(1, NA, 3, 2, 99),
myvar2 = c(1, 3, 5, 7, 7))
str(my.df)
## 'data.frame': 5 obs. of 4 variables:
## $ name : chr "Kim" "Lee" "Park" "Choi" ...
## $ gender: chr "Female" "Male" "Female" "Male" ...
## $ myvar1: num 1 NA 3 2 99
## $ myvar2: num 1 3 5 7 7
# myvar1 컬럼의 99값은 실제로 결측치로 입력한 값입니다. 이를 NA로 변경합니다.
# my.df$myvar1 의 값이 99인 요소를 선택한 다음, 그 값을 NA로 변경합니다.
$myvar1[my.df$myvar1 == 99] <- NA
my.df
# myvar2 컬럼의 7값은 실제로 결측치로 입력한 값입니다. 이를 NA로 변경합니다.
# my.df$myvar2 의 값이 7인 요소를 선택한 다음, 그 값을 NA로 변경합니다.
$myvar2[my.df$myvar2 == 7] <- NA my.df
12.3.1.2 NA를 제거한 연산
벡터의 연산을 위한 다양한 함수들에 대하여 제2부 제2장에서 살펴보았습니다. 이러한 함수들은 벡터에 NA
값이 있으면 그 결과로 NA
를 반환합니다. 이때 함수에 na.rm = TRUE
인수를 설정해 주면 벡터 요소에서 NA
를 제거하고 연산을 하게 됩니다.
# my.df의 myvar1 컬럼의 합계와 평균을 구해 보겠습니다. sum() 함수와 mean() 함수 이용
sum(my.df$myvar1) # 결과로 NA를 반환합니다.
## [1] NA
mean(my.df$myvar2) # 결과로 NA를 반환합니다.
## [1] NA
# sum() 함수와 mean() 함수에 na.rm = TRUE 인수를 지정해 줍니다.
sum(my.df$myvar1, na.rm = TRUE) # 결과로 6을 반환합니다.
## [1] 6
mean(my.df$myvar2, na.rm = TRUE) # 결과로 3을 반환합니다.
## [1] 3
complete.cases()
함수를 이용하여 데이터 세트의 각 행 별로 NA
가 존재하는지 확인할 수 있습니다. 이 complete.cases() 함수는 논리형 벡터를 반환합니다.
na.omit()
함수는 결측치가 있는 행들을 제거한 개체를 반환합니다.
예를 들어, 앞에서 my.df 데이터 프레임에 대하여 각 행 단위로 NA가 있는 행은 제거하여 새로운 데이터 세트를 생성해 보겠습니다.
# my.df 파일의 내용을 확인합니다.
# 2, 4, 5번째 행에 NA가 잆습니다. my.df
## name gender myvar1 myvar2
## 1 Kim Female 1 1
## 2 Lee Male NA 3
## 3 Park Female 3 5
## 4 Choi Male 2 NA
## 5 Suh Female NA NA
# complete.case() 함수를 이용해 보겠습니다.
<- complete.cases(my.df) # my.df의 행별로 NA가 있는지 확인합니다.
comp.index # T, F, T, F, F가 반환됩니다. comp.index
## [1] TRUE FALSE TRUE FALSE FALSE
<- my.df[comp.index, ] # comp.index가 T인 행만 선택해서 my.comp.df 개체에 복사합니다.
my.comp.df my.comp.df
## name gender myvar1 myvar2
## 1 Kim Female 1 1
## 3 Park Female 3 5
# na.omit() 함수를 이용해 보겠습니다.
<- na.omit(my.df) # my.df의 각 행에서 NA가 없는 행만 my.new.df 개체에 복사합니다.
my.new.df my.new.df
## name gender myvar1 myvar2
## 1 Kim Female 1 1
## 3 Park Female 3 5
# my.comp.df와 my.new.df는 동일한 데이터 세트 입니다. : setequal() 함수로 확인합니다.
setequal(my.comp.df, my.new.df) # TRUE를 반환합니다.
## [1] TRUE
12.3.1.3 NA
값을 다른 값으로 대체하기
데이터 프레임의 특정 컬럼에 NA
가 있는 경우 앞에서 살펴본 것처럼 NA
를 제거하고 연산을 하는 방법도 있지만, 이 NA
값을 컬럼의 대표값 예를 들면 평균값이나 중앙값 등으로 변경하여 처리하기도 합니다.
앞의 예에서 my.df
데이터 프레임의 myvar1
컬럼의 NA
값을 평균값으로 대체해 보겠습니다.
# my.df$myvar1의 NA 요소 값을 my.df$myvar1의 평균값을 대체합니다.
# my.df$myvar1 컬럼의 요소 값을 확인합니다.
$myvar1 my.df
## [1] 1 NA 3 2 NA
# 먼저 my.df$myvar1의 평균을 구합니다.
<- mean(my.df$myvar1, na.rm = TRUE) # NA를 제거한 평균을 구합니다.
mean.myvar1 # NA를 제거한 평균은 2입니다. mean.myvar1
## [1] 2
# my.df$myvar1의 요소 값이 NA인 것들을 찾아서 mean.myvar1으로 대체합니다.
$myvar1[is.na(my.df$myvar1)] <- mean.myvar1
my.df$myvar1 # NA가 모두 평균값 2로 대체되었습니다. my.df
## [1] 1 2 3 2 2
R의 대부분의 모델링 함수는 결측값을 처리하기위한 옵션을 제공합니다. 다중 대체와 같은 방법을 통해 결측값을 리스트 요소별로(행별로) 삭제하는 것 이상으로 진행할 수 있습니다. R을 통해 액세스할 수 있는 좋은 구현에는 Amelia II, Mice 그리고 mitools 등이 있습니다.13