[R] 연습

[R] 데이터 정제하기 (결측치편)

Simon Yoon 2021. 12. 1. 01:05

데이터를 다루다보면 결측치들을 마주하거나 처리해야 하는 경우도 있기 마련이다.

따라서 이번 포스팅에서는 결측치를 다루는 방법에 대한 연습을 하고자 한다.

이번에는 pima 데이터를 사용해 보고자 한다.

pima 데이터는 mlbench 패키지를 설치하고, 불러올 수 있다.

library(mlbench)
data(PimaIndiansDiabetes2)
pima <- PimaIndiansDiabetes2

 

pima 데이터의 일부


Q. 데이터셋의 결측치가 있는지 확인하고 싶다면?

A. summary(), is.na(), complete.cases() 함수를 사용하자.

 

사용 방법은 간단하다.

summary(pima)
is.na(pima)
complete.cases(pima)

이 결과 화면은 일부만 캡쳐하였다. 위의 결과 출력물을 보면서 각 함수에 대해 기본적인 설명을 하자면,

summary(pima)의 경우 단순히 결측값만을 확인하는 것이 아니라 이 데이터의 요약 통계량을 보여주는 것이다. 결측값이 있으면 마지막에 NA's : 형식으로 각 변수에 몇 개의 결측값이 존재하는지를 보여준다.

is.na(pima)의 경우 데이터프레임의 각 값이 결측값인지 아닌지를 판단한다. 결측값이면 TRUE를, 결측값이 아니면 FALSE를 출력한다. 단순히 is.na(pima)를 사용하게 되면, 사진과 같이 전체 데이터 결과를 보여주게 된다.

complete.cases(pima)의 경우 각 행에 결측값이 있는지를 판단한다. 따라서 행에 결측값이 있으면 FALSE를, 아니면 TRUE를 출력한다.

 

그러나 is.na()나 complete.cases()함수는 다른 함수와 함께 사용되는 경우도 많다. 따라서 여러 가지 사용법에 대해서 연습해야 할 필요가 있다.


Q. 좀 더 보기 좋게 칼럼별 결측치의 개수만 알고 싶다면?

A. apply(is.na(), 2, sum) 이나 colSums(is.na()) 함수를 사용하자.

 

apply(is.na(pima), 2, sum)  # 방법 1
colSums(is.na(pima))  # 방법 2
# 두 방법 모두 결과의 형태는 같다.

칼럼별 결측치 개수

참고로, 위의 예시에서 !is.na()를 사용하면 '결측값이 아닌 데이터 수'를 출력하게 된다.


Q. 결측값이 존재하는 행의 수를 확인하기 위해서는?

A. sum(complete.cases()) 함수를 사용한다.

 

sum(complete.cases(pima)) # 결측값이 존재하는 행의 수 확인
# 결과 [1] 392

이제 몇 개의 결측치가 있는 지를 열 별로, 행 별로 확인할 수 있게 되었다. 그렇다면 이 결측치들을 어떻게 처리할지 연습하겠다.

pima 데이터에서 triceps와 insulin 열에는 200개, 300개가 넘는 결측치들이 존재했는데, 이처럼 결측치가 너무 많아서 해당 칼럼을 빼고 분석해야 할 수도 있다.

 

Q. 결측치가 너무 많은 열 혹은 행을 삭제하고 싶다면?

A1. 열을 삭제하고 싶다면, 열 직접 삭제 방식으로 처리할 수 있다. 예시는 아래와 같다.

df <- df[, -c(4, 5)]

A2. 행을 삭제하고 싶다면, !is.na() / complete.cases() / filter() / na.omit() 함수를 사용할 수 있다. 사용법은 아래와 같다.

df[!is.na(df), ]
df[complete.cases(df), ]
df %>% filter(!is.na(df))  # dplyr 패키지 필요
na.omit(df)

하지만, 이처럼 완전히 제거해 버리는 방법은 분석에 필요한 데이터도 삭제해 버릴 수 있기 때문에 주의해야 한다.

보통 결측치를 쉽게 처리하기 위해서 평균값으로 대치하기도 한다.

 

Q. 결측치를 평균으로 대치하고 싶다면?

A. ifelse()를 사용하거나, 직접 평균 대치를 통해서 하는 두 가지 방식이 있다. 사용법은 아래와 같다.

df$열1 <- ifelse(is.na(df$열1), mean(df$열1, na.rm = TRUE), df$열1)
df[is.na(df$열2), "열2"] <- mean(df$열2, na.rm = TRUE)

 

예시코드에서 na.rm = TRUE 라고 했는데, 이는 결측치를 제외하고 통계량을 계산할 것을 의미한다.

mean()과 같은 통계량을 계산할 때 결측치가 있으면 [1] NA 라고 출력되며 계산이 안 되므로 주의해야 한다.

 

결측치는 항상 평균을 대입하는 것은 아니므로 데이터에 맞게 다룬다고 보면 된다. 여기서는 하나의 간단한 방식을 연습하는 것 뿐이다.

 

★ 예시문제1)

이번 편에서의 예시문제는 <빅데이터 분석기사 예시 문제로 연습하기> 포스팅의 두 번째 문제로 보면 좋을 것이다.

2021.11.28 - [[R] 연습] - [R] 빅데이터 분석기사 예시 문제로 연습하기