17. 결측치, 이상 제거
in Study on R Programming
Overview
R에서 결측치와 이상이 무엇인지 알아보고, 결측치와 이상을 제거하는 방법을 알아본다.
예제 파일1 : jumsu2.csv
예제 파일2 : dataset.csv
결측치와 이상
결측치 : Not Available 값
이상 : 표현하고자 하는 범주 바깥의 존재할 수 없는 값
결측치 제거 실습
# make sample data
name <- c('kim', 'park', 'lee', 'kang', 'shin')
gender <- c('M', 'F', NA, 'M', 'F')
score <- c(10, 20, 30, 40, NA)
df <- data.frame(name = name, gender = gender, score = score)
#####
# 결측치 확인
is.na(df)
# 결측치 개수 확인
sum(is.na(df))
# 개별 컬럼의 결측치 확인
is.na(df$gender)
# table 함수 : 빈도 확인
table(is.na(df))
# FALSE TRUE
# 13 2
library(dplyr)
# 결측치만 필터링 하기
df %>% filter(is.na(score))
df %>% filter(is.na(gender))
# name gender score
# 1 shin F NA
# name gender score
# 1 lee <NA> 30
df_nomiss <- df %>% filter(!is.na(gender) & !is.na(score))
df_nomiss
# omit 함수를 이용한 필터링
df_nomiss2 <- na.omit(df)
df_nomiss2
std <- read.csv('jumsu2.csv')
std
std[c(3, 8, 15), 'kor'] <- NA
std
# mean 함수 안에 결측치 제거
# 결측치 값을 아예 제외한 17개의 평균을 구함
std %>% summarise(mean_kor=mean(kor, na.rm = T))
table(is.na(std$kor))
mean_kor <- mean(std$kor, na.rm = T)
# 평균을 구하여, NA값에 대해 평균으로 대체
std$kor <- ifelse(is.na(std$kor), mean_kor, std$kor)
std$kor
# kor 값에 결측치가 없어진것을 확인
table(is.na(std$kor))
mean(std$kor)
# 기본값으로 대체
std[c(3, 8, 15), 'kor'] <- NA
# 기본 Default 값으로 지정하는 경우
def <- 40
std$kor <- ifelse(is.na(std$kor), def, std$kor)
std$kor
이상 보정 실습
dataset <- read.csv('dataset.csv', header = T)
dataset
sum(dataset$price, na.rm = T)
price2 <- na.omit((dataset$price))
sum(price2)
length(price2)
# 기본 값을 0이라고 가정하고, 0으로 치환
dataset$price2 <- ifelse(!is.na(dataset$price), dataset$price, 0)
# 결측치를 비결측치의 평균으로 대체하기
mean_price <- round(mean(dataset$price, na.rm = T), 2)
dataset$price3 <- ifelse(!is.na(dataset$price), dataset$price, mean_price)
# 결과
dataset[c('price', 'price2', 'price3')]
# 이상 보정
gender <- dataset$gender
table(gender)
pie(table(gender))
dataset <- subset(dataset, gender == 1 | gender == 2)
nrow(dataset)
dataset <- read.csv('dataset.csv', header = T)
dataset
length(dataset$price)
plot(dataset$price)
mybox <- boxplot(dataset$price)
mybox$stats
dataset2 <- subset(dataset, dataset$price > 2.1 & dataset$price < 7.9)
length(dataset2$price)
sort(dataset2$price)
# stem : 왼쪽 열이 1단위 / 오른쪽 열이 .단위의 개수
stem(dataset2$price)
summary(dataset$age)
결측치 제거와 이상 보정
# 성별 : 1, 2
# 점수 : 1 ~ 5
# 이상 : 표현하고자 하는 범주 바깥의 존재할 수 없는 값
gender <- c(1, 2, 3, 1, 2, 1, 2)
score <- c(2, 3, 1, 5, 2, 20, 4)
outlier <- data.frame(gender = gender, score = score)
outlier
sort(unique(outlier$gender))
sort(unique(outlier$score))
table(outlier$gender)
# gender에서 1, 2가 아닌 값이면 NA로 치환
outlier$gender <- ifelse(outlier$gender != 1 & outlier$gender != 2, NA, outlier$gender)
outlier
# useNA = 'ifany' : NA 보기
table(outlier$gender, useNA = 'ifany')
# score에서 1~5가 아닌 값이면 NA로 치환
# condition의 값을 별도로 둘 수 있음
cond <- outlier$score < 1 | outlier$score > 5 # T or F
outlier$score <- ifelse(cond, NA, outlier$score)
outlier
# useNA = 'ifany' : NA 보기
table(outlier$score, useNA = 'ifany')
library(dplyr)
# NA값 필터링 후 평균값 구하기
outlier %>% filter(!is.na(gender) & !is.na(score)) %>% group_by(gender) %>% summarise(mean_score = mean(score))
# # A tibble: 2 x 2
# gender mean_score
# <dbl> <dbl>
# 1 3.5
# 2 3
# boxplot : 데이터의 분포를 볼 수 있음
boxplot(score)
# ggplot2 에서 제공하는 데이터 셋을 이용한 이상 확인
library(ggplot2)
str(mpg)
range(mpg$hwy)
sort(unique(mpg$hwy))
mybox <- boxplot(mpg$hwy)
attributes(mybox)
# stats : Dataframe의 통계 정보를 알려준다.
mybox$stats
sort(mpg$hwy)
mpg$hwy <- ifelse(mpg$hwy < 12 | mpg$hwy > 37, NA, mpg$hwy)
table(is.na(mpg$hwy))
# drv : 자동차 구동 방식
res <- mpg %>% group_by(drv) %>% summarise(mean_hwy = mean(hwy, na.rm = T))
res