# [ 연습문제 - Boston_na.csv 데이터에 대한 결측치 대치 ]
# 1. 데이터 로딩
df <- read.csv('Boston_na.csv')
# 변수 설명
# crim 범죄율
# zn 25,000 sq.ft 이상 주거지 비율
# indus 비소매 상업지구 비율
# chas 찰스강 인접 여부 (1=인접)
# nox 일산화질소 농도
# rm 평균 방 개수
# age 1940년 이전 건축 비율
# dis 고용센터까지 거리
# rad 고속도로 접근성
# tax 재산세율
# ptratio 학생/교사 비율
# black 흑인 인구 비율
# lstat 하위계층 비율
# medv 주택 중앙값 (단위: $1000)
# 컬럼별 결측치 수 확인
colSums(is.na(df))
# medv : 방이 많을수록 집값 높음 → 강한 양의 상관
# lstat : 하위계층 비율 높은 지역은 방 개수 적은 경향
# indus : 공업지구일수록 주거 환경(방 크기) 다름
# nox : 환경 수준이 주거 형태와 연관
# age : 오래된 건물일수록 방 구조 다름
# 2. 결측치 대치
# 1) 전체 평균으로 대치
# 2) chas 변수별 평균으로 대치
# 3) knn imputer
[ 내 답안 ]
df <- read.csv("Boston_na.csv")
head(df)
> head(df)
crim zn indus chas nox rm age dis rad tax ptratio black lstat medv
1 0.00632 18 2.31 0 0.538 6.575 65.2 4.09 1 296 15.3 396.90 4.98 24.0
2 0.02731 0 7.07 0 0.469 6.421 78.9 4.9671 2 242 17.8 396.90 9.14 21.6
3 0.02729 0 7.07 0 0.469 7.185 61.1 4.9671 2 242 17.8 392.83 4.03 34.7
4 0.03237 0 2.18 0 0.458 6.998 45.8 6.0622 3 222 18.7 394.63 2.94 33.4
5 0.06905 0 2.18 0 0.458 7.147 54.2 6.0622 3 222 18.7 396.90 5.33 36.2
6 0.02985 0 2.18 0 0.458 6.430 58.7 3 222 18.7 394.12 5.21 28.7
# 컬럼별 결측치 수 확인
colSums(is.na(df))
> colSums(is.na(df))
crim zn indus chas nox rm age dis rad tax ptratio black lstat medv
0 0 0 0 0 13 0 0 0 0 0 0 0 0
# 2. 결측치 대치
# 1) 전체 평균으로 대치
# 데이터 프레임 복사
df_imp1 <- df
# 전체 평균으로 대치 진행
total_rm <- mean(df$rm, na.rm=T)
df_imp1$rm[is.na(df_imp1$rm)] <- total_rm
sum(is.na(df_imp1$rm))
# 2) chas 변수별 평균으로 대치
library(plyr)
ddply(df_imp2, .(chas), summarise, mean_rm = mean(rm, na.rm=T))
df_imp2 <- ddply(df_imp2, .(chas), mutate, rm = ifelse(is.na(rm), mean(rm, na.rm=T), rm))
sum(is.na(df_imp2$rm))
# 3) knn imputer
# 데이터 프레임 복사
df_imp3 <- df
# 대치 진행
library(VIM)
df_imp3 <- kNN(df_imp3, variable = 'rm', dist_var = c('zn', 'age', 'tax', 'ptratio', 'lstat', 'medv'), k=5, imp_var=F)
sum(is.na(df_imp3$rm))
# 데이터 프레임 복사
df_imp4 <- df
# 대치 진행 (예제문제에 제시된 변수)
library(VIM)
df_imp4 <- kNN(df_imp4, variable = 'rm', dist_var = c('medv', 'lstat', 'indus', 'nox', 'age'), k=5, imp_var=F)
sum(is.na(df_imp4$rm))
# 성능 비교
library(randomForest)
# randomForest 학습을 위한 종속변수의 factor 타입 변경(필수)
df_imp1$rm <- factor(df_imp1$rm)
df_imp2$rm <- factor(df_imp2$rm)
df_imp3$rm <- factor(df_imp3$rm)
df_imp4$rm <- factor(df_imp4$rm)
# 학습
set.seed(0)
rf1 <- randomForest(rm ~ ., data = df_imp1, ntree = 100)
set.seed(0)
rf2 <- randomForest(rm ~ ., data = df_imp2, ntree = 100)
set.seed(0)
rf3 <- randomForest(rm ~ ., data = df_imp3, ntree = 100)
set.seed(0)
rf4 <- randomForest(rm ~ ., data = df_imp4, ntree = 100)
# accuracy
sum(df_imp1$rm == rf1$predicted) / nrow(df) * 100
sum(df_imp2$rm == rf2$predicted) / nrow(df) * 100
sum(df_imp3$rm == rf3$predicted) / nrow(df) * 100
sum(df_imp4$rm == rf4$predicted) / nrow(df) * 100
> sum(df_imp1$rm == rf1$predicted) / nrow(df) * 100
[1] 0.1976285
> sum(df_imp2$rm == rf2$predicted) / nrow(df) * 100
[1] 0.1976285
> sum(df_imp3$rm == rf3$predicted) / nrow(df) * 100
[1] 1.581028
> sum(df_imp4$rm == rf4$predicted) / nrow(df) * 100
[1] 0.5928854
# OOB accuracy 비교
data.frame(
방법 = c("전체평균 대치", "그룹평균 대치", "모든변수 KNN", "관련변수 KNN"),
Accuracy = round(c(1 - rf1$err.rate[100, "OOB"],
1 - rf2$err.rate[100, "OOB"],
1 - rf3$err.rate[100, "OOB"],
1 - rf4$err.rate[100, "OOB"]), 4)
)
> # OOB accuracy 비교
> data.frame(
+ 방법 = c("전체평균 대치", "그룹평균 대치", "모든변수 KNN", "관련변수 KNN"),
+ Accuracy = round(c(1 - rf1$err.rate[100, "OOB"],
+ 1 - rf2$err.rate[100, "OOB"],
+ 1 - rf3$err.rate[100, "OOB"],
+ 1 - rf4$err.rate[100, "OOB"]), 4)
+ )
방법 Accuracy
1 전체평균 대치 0.0020
2 그룹평균 대치 0.0020
3 모든변수 KNN 0.0158
4 관련변수 KNN 0.0059
# ** 반복 평가 점수 확인
n_iter <- 30
result <- data.frame(iter = 1:n_iter, imp1 = NA, imp2 = NA, imp3 = NA, imp4 = NA)
for (i in 1:n_iter) {
set.seed(i)
rf1 <- randomForest(rm ~ ., data = df_imp1, ntree = 100)
rf2 <- randomForest(rm ~ ., data = df_imp2, ntree = 100)
rf3 <- randomForest(rm ~ ., data = df_imp3, ntree = 100)
rf4 <- randomForest(rm ~ ., data = df_imp4, ntree = 100)
result$imp1[i] <- 1 - rf1$err.rate[100, 'OOB']
result$imp2[i] <- 1 - rf2$err.rate[100, 'OOB']
result$imp3[i] <- 1 - rf3$err.rate[100, 'OOB']
result$imp4[i] <- 1 - rf4$err.rate[100, 'OOB']
}
result
colMeans(result[,-1])
> colMeans(result[,-1])
imp1 imp2 imp3 imp4
0.0009881423 0.0005270092 0.0160079051 0.0070487484
[ 문제풀이 ]
# 1. 데이터 로딩
df <- read.csv('Boston_na.csv')
# 변수 설명
# crim 범죄율
# zn 25,000 sq.ft 이상 주거지 비율
# indus 비소매 상업지구 비율
# chas 찰스강 인접 여부 (1=인접)
# nox 일산화질소 농도
# rm 평균 방 개수
# age 1940년 이전 건축 비율
# dis 고용센터까지 거리
# rad 고속도로 접근성
# tax 재산세율
# ptratio 학생/교사 비율
# black 흑인 인구 비율
# lstat 하위계층 비율
# medv주택 중앙값 (단위: $1000)
# 컬럼별 결측치 수 확인
colSums(is.na(df))
# medv : 방이 많을수록 집값 높음 → 강한 양의 상관
# lstat : 하위계층 비율 높은 지역은 방 개수 적은 경향
# indus : 공업지구일수록 주거 환경(방 크기) 다름
# nox : 환경 수준이 주거 형태와 연관
# age : 오래된 건물일수록 방 구조 다름
# 2. 결측치 대치
# 1) 전체 평균으로 대치
df_imp1 <- df
df_imp1$rm[is.na(df_imp1$rm)] <- mean(df_imp1$rm, na.rm = T)
sum(is.na(df_imp1$rm))
# 2) chas 변수별 평균으로 대치
library(plyr)
df_imp2 <- df
df_imp2 <- ddply(df_imp2, .(chas), mutate,
rm = ifelse(is.na(rm), mean(rm, na.rm = T), rm))
sum(is.na(df_imp2$rm))
# 3) knn imputer
library(VIM)
# 3-1) 모든 컬럼 사용
X <- df[,-ncol(df)]
df_imp3 <- kNN(X, variable = 'rm', dist_var = colnames(X), k = 5, imp_var = F)
df_imp3$medv <- df$medv
sum(is.na(df_imp3$income))
# 3-2) 필요 컬럼 사용
df_imp4 <- kNN(X, variable = 'rm',
dist_var = c('lstat', 'indus', 'nox', 'age'), k = 5, imp_var = F)
df_imp4$medv <- df$medv
sum(is.na(df_imp4$income))
# 3. 성능비교
library(randomForest)
sum(is.na(df_imp2$rm))
# 학습
set.seed(0)
rf1 <- randomForest(medv ~ ., data = df_imp1, ntree = 100)
rf2 <- randomForest(medv ~ ., data = df_imp2, ntree = 100)
rf3 <- randomForest(medv ~ ., data = df_imp3, ntree = 100)
rf4 <- randomForest(medv ~ ., data = df_imp4, ntree = 100)
# mse
library(Metrics)
mse(df$medv, rf1$predicted) # 12.30664
mse(df$medv, rf2$predicted) # 131.8262
mse(df$medv, rf3$predicted) # 12.65105
mse(df$medv, rf4$predicted) # 10.67851
'아이티윌_데이터 분석 55기 > 문제풀이_통계 및 분석' 카테고리의 다른 글
| #15-2. 15일차 퀴즈에 대한 문제풀이 (0) | 2026.05.06 |
|---|---|
| #13-2. 13일차 퀴즈에 대한 문제풀이 (0) | 2026.04.29 |
| #11-2. 11일차 퀴즈에 대한 문제풀이 (0) | 2026.04.27 |
| #7-2. 7일차 퀴즈에 대한 문제풀이 (0) | 2026.04.21 |
| #5-2. 5일차 퀴즈에 대한 문제풀이 (0) | 2026.04.17 |