학습할 때 사용하는 데이터셋은 바로 사용할 수 있는 정제된 데이터셋을 이용하는 경우가 많지만 실전에서 얻는 데이터는 그렇지 않은 경우가 대부분이다.
일부 데이터는 값이 들어가있지 않고 ( 결측치 ), 설령 값이 들어가있다고 하더라도 올바른 값이 들어있지 않을 수가 있다. ( 이상치 )
이런 데이터를 분석하기 위해서는 먼저 결측치와 이상치를 처리해야 한다.
결측치란 누락된 값, 비어있는 값을 의미한다.
R에서는 이 값이 NA로 표시된다.
아래는 나이에 따라 받은 점수를 담은 데이터셋이다.
df <- data.frame(age=c(18,17,NA,18,17),score=c(70,50,90,80,NA))
데이터셋에 NA값이 들어가있는지 확인하고 싶을 때는 is.na() 함수를 사용하면 된다.
is.na(df)
간단하게 NA 값이 몇개씩 들어있는지 확인할 수도 있다.
table(is.na(df))
TRUE 가 NA값의 개수다.
모든 학생이 받은 점수의 평균을 내고 싶다고 가정하자.
이때 NA 값을 포함한 상태에서 구하면 결과로 NA 값이 나온다.
컴퓨터는 총 점수를 모든 학생 수(5)로 나눌지, 점수가 존재하는 학생 수(4)로 나눌지 알 수 없다. 따라서 우리가 기준을 정해야 한다.
mean(df$score) # NA
결측치를 정제하는 방법에는 두가지가 있다.
- 결측치를 포함한 행을 제외하고 값을 산출한다.
- 결측치를 다른 값 (ex 평균)으로 바꾼 다음 값을 산출한다.
먼저 결측치를 포함한 행을 제외하는 방법이다.
filter()
아니면 na.omit()
을 사용할 수 있다.
먼저 filter()
를 사용하는 방법이다.
df %>% filter(!is.na(age) & !is.na(score))
age & score 중 NA가 아닌 행을 추출했다.
na.omit()
을 사용하면 간단하다.
na.omit(df)
이렇게 해도 같은 결과가 나온다.
다만 na.omit()
은 NA 값을 포함한 행을 모두 없애버리는데 반해 filter()
는 선택해서 삭제할 수 있으므로 상황에 맞게 골라 쓰면 된다.
mean(df$score, na.rm = T) # 72.5
mean()
함수의 두번째 인자로 na.rm 값을 TRUE로 설정하면 NA 값을 포함하는 행을 제외하고 계산한 결과가 나온다.
만약 결측치(NA)를 제외해서 표본의 수가 적다고 느껴진다면 임의의 값으로 변환할 수 있다.
변환하는 방법에는 여러 복잡한 방법들이 있지만 오늘은 전체의 평균으로 바꾸는 방법만 다뤄보겠다.
ifelse()
함수를 사용해서 간단하게 해결할 수 있다.
df$score <- ifelse(is.na(df$score), mean(df$score, na.rm = T), df$score)
만약 score 의 값이 NA 면 평균값으로 바꾸고 아니면 그대로 둔다는 함수이다.
만약 나이와 점수의 데이터를 받아왔는데 결과가 다음처럼 나타날 수 있다.
df <- data.frame(age=c(18,17,18,18,17),score=c(70,50,90,500,80))
결과를 보면 뜬금없이 500이란 점수가 나타났다.
이처럼 일정 패턴에서 벗어난 값을 이상치라고 한다.
만약 데이터에 이상치가 있으면 모두 NA 값으로 바꾸면 된다.
기준은 '100점을 넘으면' 으로 잡았다.
df$score <- ifelse(df$score > 100, NA, df$score)
이것 역시 ifelse()
함수로 간단하게 처리할 수 있다.
만약 주어진 데이터가 월간 코로나 확진자의 수를 나타내고 있다면 갑작스런 확진자 폭증으로 이상치가 생길 수 있다. 이때도 위와 같은 방법으로 이상치를 처리하면 잘못된 데이터가 나와서 막대한 피해를 입을 수 있다.
이처럼 이상치는 데이터의 특성에 따라 얼마든지 존재할 수 있으므로 처리 시 각별한 주의가 필요하다.