본문 바로가기

데이터 마이닝

WineQuality 분석

치킨 6조 자료입니다.zip
2.87MB

# -------------------------------------------------------------------------------- #
#
#                           ---- WineQuality ----
#
# -------------------------------------------------------------------------------- #

# 기간 : 2019-7-19 ~ 2019-7-26
# 참가인원 : 김석준, 김영인, 오창민, 이현영
# 김석준 : 데이터 전처리, 군집분석, SOM, 주성분분석, 인공신경망
# 김영인 : 의사결정나무
# 오창민 : 나이브 베이즈 분류기
# 이현영 : SVM

# install.packages("tidyverse")
# install.packages("rJava")
# install.packages("DBI")
# install.packages("RMySQL")
# install.packages("rpart")
# install.packages("e1071")
# install.packages("NeuralNetTools")
# install.packages("neuralnet")
# install.packages("caret")
# install.packages("kohonen")
# install.packages("klaR")
library(kohonen);library(nnet);library(caret)
library(NeuralNetTools);library(e1071);library(rpart)
library(klaR);library(ggplot2);library(dplyr);library(readr)

redwine <- read_delim(file="H:\\R데이터분석\\데이터\\와인\\winequality-red.csv",delim=";")
# 레드와인
whitewine <- read_delim(file="H:\\R데이터분석\\데이터\\와인\\winequality-white.csv",delim=";")
# 화이트와인

# readr의 read_delim()는 read.table()와 비슷한 기능을 한다.

# -------------------------------------------------------------------------------- #
#
#                         ---- 1. 데이터 탐색(수치) ----
#
# -------------------------------------------------------------------------------- #
str(redwine) # 레드와인
str(whitewine) # 화이트와인
# ---------------- #
# fixed acidity - 고정산도 -> fixed
# volatile acidity - 휘발성 산도 -> volatile
# citric acid - 구연산 -> citric
# residual sugar - 잔류 설탕 -> sugar
# chlorides - 염화물 -> chlorides
# free sulfur dioxide - 자유 이산화황 -> fsd
# total sulfur dioxide - 총 이산화황 -> tsd
# density - 밀도 -> density
# pH - 산도 - >ph
# sulphates - 황산염 -> sulphates
# alcohol - 알코올 -> alcohol
# Output variable (based on sensory data): 
# quality (score between 0 and 10) - 와인의 품질(종속변수) -> quality
# ---------------- #
# 변수명의 변경
# quality(와인품질)은 사람이 매긴 점수이므로 factor로 변환한다.
# quality는 0에서 10까지의 값을 가진다.
# 결측값은 존재하지 않는다.

# -- 이름 변경 -- #
name <- c("fixed", "volatile", "citric", "sugar", "chlorides", "fsd", "tsd", 
          "density", "ph", "sulphates", "alcohol", "quality") # 열의 이름
names(redwine) <- name
names(whitewine) <- name

# -- quality factor로 변경 -- #
redwine <- redwine %>% mutate(quality = factor(quality))
whitewine <- whitewine %>% mutate(quality = factor(quality))

# -- 기초통계량 -- #
summary(redwine)
summary(whitewine)
# 두 데이터 프레임을 하나로 만들어 분석한다.
# white와인에서 높은 점수를 주는 속성과 레드와인에서 높은 점수를 주는 속성이
# 무엇인지 확인하고 점수를 예측하는 모형을 만든다.
# 또 점수와 속성들로 어떤 와인인지 예측한다.

# -- 데이터 통합 -- #
wine <- rbind(redwine %>% mutate(type = "red"), 
              whitewine %>% mutate(type = "white"))
# 두 데이터를 하나로 합치며 type으로 구분
wine <- wine %>% mutate(type = factor(type)) # type을 factor로 바꾼다.
name <- c(name,"type")

# -- 기초통계량(wine) -- #
str(wine)
summary(wine)

dbWriteTable(con, name = "wine", value = wine, overwrite = TRUE, temporary = FALSE)

rm(list = setdiff(ls(), c("con"))) # 필요없는 변수 제거
# -------------------------------------------------------------------------------- #
#
#                         ---- 1. 데이터 탐색(그림) ----
#
# -------------------------------------------------------------------------------- #
dbListTables(con)
wine <- tbl(con, "wine") # 데이터 베이스의 값을 불러온다.
wine <- collect(wine) %>% 
  mutate(quality = factor(quality),
         type = factor(type)) %>% 
  select(-row_names)

# -------- wine quality와 비교 --------
# ---- 1) 고정산도 ----
# -- 고정산도 -- #
ggplot(data = wine, aes(x=fixed, y = ..density..)) +
  geom_histogram(bins = 20, colour = "#ffffff", fill = "#5daa5d")+
  geom_line(stat="density", colour= "blue")+
  ggtitle("고정산도") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# -- 고정산도 vs type -- #
ggplot(data = wine, aes(x=fixed, y = ..density..)) +
  geom_histogram(bins = 20, colour = "#ffffff", fill = "#5daa5d")+
  geom_line(stat="density", colour= "blue")+
  facet_grid(type ~ .) +
  ggtitle("고정산도 vs type") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))
# white와인의 산도가 red와인의 산도보다 대부분 작다.

# -- 고정산도 vs quality -- #
ggplot(data = wine, aes(x = quality, y = fixed, fill = quality)) +
  geom_boxplot(outlier.colour = "red") +
  ggtitle("고정산도 vs quality") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# -- 고정산도 vs quality, type -- #
ggplot(data = wine, aes(x = quality, y = fixed, fill = quality)) +
  geom_boxplot(outlier.colour = "red") +
  facet_grid(type ~ .)+
  ggtitle("고정산도 vs quality") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# ---- 2) 휘발성 산도 ----
# -- 휘발성 산도 -- #
ggplot(data = wine, aes(x=volatile, y = ..density..)) +
  geom_histogram(bins = 20, colour = "#ffffff", fill = "#5daa5d")+
  geom_line(stat="density", colour= "blue")+
  ggtitle("휘발성 산도") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# -- 휘발성 산도 vs type -- #
ggplot(data = wine, aes(x=volatile, y = ..density..)) +
  geom_histogram(bins = 20, colour = "#ffffff", fill = "#5daa5d")+
  geom_line(stat="density", colour= "blue")+
  facet_grid(type ~ .) +
  ggtitle("휘발성 산도 vs type") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))
# white와인의 산도가 red와인의 산도보다 대부분 작다.

# -- 휘발성 산도 vs quality -- #
ggplot(data = wine, aes(x = quality, y = volatile, fill = quality)) +
  geom_boxplot(outlier.colour = "red") +
  ggtitle("휘발성 산도 vs quality") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# -- 휘발성 산도 vs quality, type -- #
ggplot(data = wine, aes(x = quality, y = volatile, fill = quality)) +
  geom_boxplot(outlier.colour = "red") +
  facet_grid(type ~ .)+
  ggtitle("휘발성 산도 vs quality") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# ---- 3) 구연산 ----
# -- 구연산 -- #
ggplot(data = wine, aes(x=citric, y = ..density..)) +
  geom_histogram(bins = 20, colour = "#ffffff", fill = "#5daa5d")+
  geom_line(stat="density", colour= "blue")+
  ggtitle("구연산") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# -- 구연산 vs type -- #
ggplot(data = wine, aes(x=citric, y = ..density..)) +
  geom_histogram(bins = 20, colour = "#ffffff", fill = "#5daa5d")+
  geom_line(stat="density", colour= "blue")+
  facet_grid(type ~ .) +
  ggtitle("구연산 vs type") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))
# white와인은 red와인보다 더 중앙으로 뭉쳐있다.

# -- 구연산 vs quality -- #
ggplot(data = wine, aes(x = quality, y = citric, fill = quality)) +
  geom_boxplot(outlier.colour = "red") +
  ggtitle("구연산 vs quality") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# -- 구연산 vs quality, type -- #
ggplot(data = wine, aes(x = quality, y = citric, fill = quality)) +
  geom_boxplot(outlier.colour = "red") +
  facet_grid(type ~ .)+
  ggtitle("구연산 vs quality") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# ---- 4) 잔류설탕 ----
# -- 잔류설탕 -- #
ggplot(data = wine, aes(x=sugar, y = ..density..)) +
  geom_histogram(bins = 20, colour = "#ffffff", fill = "#5daa5d")+
  geom_line(stat="density", colour= "blue")+
  ggtitle("잔류설탕") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# -- 잔류설탕 vs type -- #
ggplot(data = wine, aes(x=sugar, y = ..density..)) +
  geom_histogram(bins = 20, colour = "#ffffff", fill = "#5daa5d")+
  geom_line(stat="density", colour= "blue")+
  facet_grid(type ~ .) +
  ggtitle("잔류설탕 vs type") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))
# 잔류설탕은 red와인이 white와인보다 더 적다.

# -- 잔류설탕 vs quality -- #
ggplot(data = wine, aes(x = quality, y = sugar, fill = quality)) +
  geom_boxplot(outlier.colour = "red") +
  ggtitle("잔류설탕 vs quality") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# -- 잔류설탕 vs quality, type -- #
ggplot(data = wine, aes(x = quality, y = sugar, fill = quality)) +
  geom_boxplot(outlier.colour = "red") +
  facet_grid(type ~ .)+
  ggtitle("잔류설탕 vs quality") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# ---- 5) 염화물 ----
# -- 염화물 -- #
ggplot(data = wine, aes(x=chlorides , y = ..density..)) +
  geom_histogram(bins = 20, colour = "#ffffff", fill = "#5daa5d")+
  geom_line(stat="density", colour= "blue")+
  ggtitle("염화물") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# -- 염화물 vs type -- #
ggplot(data = wine, aes(x=chlorides , y = ..density..)) +
  geom_histogram(bins = 20, colour = "#ffffff", fill = "#5daa5d")+
  geom_line(stat="density", colour= "blue")+
  facet_grid(type ~ .) +
  ggtitle("염화물 vs type") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))
# 염화물은 red와인이 white와인보다 더 많이 있다.

# -- 염화물 vs quality -- #
ggplot(data = wine, aes(x = quality, y = chlorides , fill = quality)) +
  geom_boxplot(outlier.colour = "red") +
  ggtitle("염화물 vs quality") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# -- 염화물 vs quality, type -- #
ggplot(data = wine, aes(x = quality, y = chlorides , fill = quality)) +
  geom_boxplot(outlier.colour = "red") +
  facet_grid(type ~ .)+
  ggtitle("염화물 vs quality") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# ---- 6) 자유 이산화황 ----
# -- 자유 이산화황 -- #
ggplot(data = wine, aes(x=fsd , y = ..density..)) +
  geom_histogram(bins = 20, colour = "#ffffff", fill = "#5daa5d")+
  geom_line(stat="density", colour= "blue")+
  ggtitle("자유 이산화황") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# -- 자유 이산화황 vs type -- #
ggplot(data = wine, aes(x=fsd , y = ..density..)) +
  geom_histogram(bins = 20, colour = "#ffffff", fill = "#5daa5d")+
  geom_line(stat="density", colour= "blue")+
  facet_grid(type ~ .) +
  ggtitle("자유 이산화황 vs type") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))
# 자유 이산화황은 red wine과 white wine이 별 차이가 없다.

# -- 자유 이산화황 vs quality -- #
ggplot(data = wine, aes(x = quality, y = fsd , fill = quality)) +
  geom_boxplot(outlier.colour = "red") +
  ggtitle("자유 이산화황 vs quality") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# -- 자유 이산화황 vs quality, type -- #
ggplot(data = wine, aes(x = quality, y = fsd , fill = quality)) +
  geom_boxplot(outlier.colour = "red") +
  facet_grid(type ~ .)+
  ggtitle("자유 이산화황 vs quality") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# ---- 7) 총 이산화황 ----
# -- 총 이산화황 -- #
ggplot(data = wine, aes(x=tsd , y = ..density..)) +
  geom_histogram(bins = 20, colour = "#ffffff", fill = "#5daa5d")+
  geom_line(stat="density", colour= "blue")+
  ggtitle("총 이산화황") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# -- 총 이산화황 vs type -- #
ggplot(data = wine, aes(x=tsd , y = ..density..)) +
  geom_histogram(bins = 20, colour = "#ffffff", fill = "#5daa5d")+
  geom_line(stat="density", colour= "blue")+
  facet_grid(type ~ .) +
  ggtitle("총 이산화황 vs type") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))
# white wine이 red wine보다 대부분 이산화황이 더 많은 것을 알 수 있다.

# -- 총 이산화황 vs quality -- #
ggplot(data = wine, aes(x = quality, y = tsd , fill = quality)) +
  geom_boxplot(outlier.colour = "red") +
  ggtitle("총 이산화황 vs quality") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# -- 총 이산화황 vs quality, type -- #
ggplot(data = wine, aes(x = quality, y = tsd , fill = quality)) +
  geom_boxplot(outlier.colour = "red") +
  facet_grid(type ~ .)+
  ggtitle("총 이산화황 vs quality") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# ---- 8) 밀도 ----
# -- 밀도 -- #
ggplot(data = wine, aes(x=density , y = ..density..)) +
  geom_histogram(bins = 20, colour = "#ffffff", fill = "#5daa5d")+
  geom_line(stat="density", colour= "blue")+
  ggtitle("밀도") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# -- 밀도 vs type -- #
ggplot(data = wine, aes(x=density , y = ..density..)) +
  geom_histogram(bins = 20, colour = "#ffffff", fill = "#5daa5d")+
  geom_line(stat="density", colour= "blue")+
  facet_grid(type ~ .) +
  ggtitle("밀도 vs type") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))
# whie wine보다 red wine이 오른쪽으로 더 치우쳐 젔다.

# -- 밀도 vs quality -- #
ggplot(data = wine, aes(x = quality, y = density , fill = quality)) +
  geom_boxplot(outlier.colour = "red") +
  ggtitle("밀도 vs quality") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))
# 밀도가 낯으면 좋은 품질일 수 도 있다.

# -- 밀도 vs quality, type -- #
ggplot(data = wine, aes(x = quality, y = density , fill = quality)) +
  geom_boxplot(outlier.colour = "red") +
  facet_grid(type ~ .)+
  ggtitle("밀도 vs quality") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))


# ---- 9) 산도 ----
# -- 산도 -- #
ggplot(data = wine, aes(x=ph , y = ..density..)) +
  geom_histogram(bins = 20, colour = "#ffffff", fill = "#5daa5d")+
  geom_line(stat="density", colour= "blue")+
  ggtitle("산도") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))
# 분토가 정규분포에 근사하는  것 같아 보인다.

# -- 산도 vs type -- #
ggplot(data = wine, aes(x=ph , y = ..density..)) +
  geom_histogram(bins = 20, colour = "#ffffff", fill = "#5daa5d")+
  geom_line(stat="density", colour= "blue")+
  facet_grid(type ~ .) +
  ggtitle("산도 vs type") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))
# white wine의 분포가 정규분포처럼 보인다.

# -- 산도 vs quality -- #
ggplot(data = wine, aes(x = quality, y = ph , fill = quality)) +
  geom_boxplot(outlier.colour = "red") +
  ggtitle("산도 vs quality") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# -- 산도 vs quality, type -- #
ggplot(data = wine, aes(x = quality, y = ph , fill = quality)) +
  geom_boxplot(outlier.colour = "red") +
  facet_grid(type ~ .)+
  ggtitle("산도 vs quality") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# ---- 10) 황산염 ----
# -- 황산염 -- #
ggplot(data = wine, aes(x=sulphates , y = ..density..)) +
  geom_histogram(bins = 20, colour = "#ffffff", fill = "#5daa5d")+
  geom_line(stat="density", colour= "blue")+
  ggtitle("황산염") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# -- 황산염 vs type -- #
ggplot(data = wine, aes(x=sulphates , y = ..density..)) +
  geom_histogram(bins = 20, colour = "#ffffff", fill = "#5daa5d")+
  geom_line(stat="density", colour= "blue")+
  facet_grid(type ~ .) +
  ggtitle("황산염 vs type") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# -- 황산염 vs quality -- #
ggplot(data = wine, aes(x = quality, y = sulphates , fill = quality)) +
  geom_boxplot(outlier.colour = "red") +
  ggtitle("황산염 vs quality") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# -- 황산염 vs quality, type -- #
ggplot(data = wine, aes(x = quality, y = sulphates , fill = quality)) +
  geom_boxplot(outlier.colour = "red") +
  facet_grid(type ~ .)+
  ggtitle("황산염 vs quality") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))
# red wine에서 황산염이 높으면 좋은 품질일수 있을 것 같다.

# ---- 11) 알코올 ----
# -- 알코올 -- #
ggplot(data = wine, aes(x=alcohol , y = ..density..)) +
  geom_histogram(bins = 20, colour = "#ffffff", fill = "#5daa5d")+
  geom_line(stat="density", colour= "blue")+
  ggtitle("알코올") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# -- 알코올 vs type -- #
ggplot(data = wine, aes(x=alcohol , y = ..density..)) +
  geom_histogram(bins = 20, colour = "#ffffff", fill = "#5daa5d")+
  geom_line(stat="density", colour= "blue")+
  facet_grid(type ~ .) +
  ggtitle("알코올 vs type") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))

# -- 알코올 vs quality -- #
ggplot(data = wine, aes(x = quality, y = alcohol , fill = quality)) +
  geom_boxplot(outlier.colour = "red") +
  ggtitle("알코올 vs quality") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))
# 알코올의 도수가 높으면 품질이 높다고 예측된다.

# -- 알코올 vs quality, type -- #
ggplot(data = wine, aes(x = quality, y = alcohol , fill = quality)) +
  geom_boxplot(outlier.colour = "red") +
  facet_grid(type ~ .)+
  ggtitle("알코올 vs quality") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size = 20, colour = "#112211"))
# red wine과 white wine에서도 같이 예측된다.

# ---- 12)각 독립변수들의 상관관계 분석 ----
pairs(wine %>% select(-c(type, quality)))
corr <- cor(wine %>% select(-c(type, quality)),method = "pearson")
abs(corr)>=0.5
# density-sugar
# fsd-tsd
# density-alcohol
# sd = fsd/tsd로 새로운 변수를 만들어 사용한다.
# density는 분석에서 제외한다.



# -------------------------------------------------------------------------------- #
#
#                         ---- 2. 데이터 전처리 ----
#
# -------------------------------------------------------------------------------- #

# -------- 1) 각 변수들의 정규화후 분포 분석 --------
wine <- wine %>% 
  mutate(quality_g =ifelse(quality %in% c("1","2","3","4"),"하급",
                           ifelse(quality %in% c("5","6","7"), "중급","상급")) %>% 
           factor(levels = c("하급","중급","상급")),
         sd = fsd/tsd) %>% # 총 이산화황에서 자유 이산화황의 비율
  select(-c(fsd,tsd,density))
# -- 상관계수 확인 -- #
wineCor <- cor(wine %>% select(-c(type, quality,quality_g)))
abs(wineCor) >= 0.4
pairs(wine %>% select(-c(type, quality,quality_g)))
# 산점도 행렬과 상관계수를 가지고 분석한 결과
# 각 독립변수들은 서로 독립이라고 가정할 수 있다.

# 훈련 데이터(70%)와 검사 데이터로 구분 
set.seed(20190724)
train <- wine %>% group_by(type, quality_g) %>% sample_frac(0.7) %>% group_by()
test <- anti_join(wine, train)

# 정규화 
train2 <- train %>% group_by(type) %>% 
  mutate(fixed = scale(fixed),
          volatile = scale(volatile),
          citric = scale(citric),
          sugar = scale(sugar),
          chlorides = scale(chlorides),
          sd = scale(sd),
          ph = scale(ph),
          sulphates = scale(sulphates),
          alcohol = scale(alcohol)) %>% 
  group_by()

test2 <- test %>% group_by(type) %>% 
  mutate(fixed = scale(fixed),
         volatile = scale(volatile),
         citric = scale(citric),
         sugar = scale(sugar),
         chlorides = scale(chlorides),
         sd = scale(sd),
         ph = scale(ph),
         sulphates = scale(sulphates),
         alcohol = scale(alcohol)) %>% 
  group_by()

base2 <- ggplot(data = train2)

# ---- quality ----
base2 + geom_bar(aes(x = quality), stat = "count",
                 fill = "green", col= "black") +
  ggtitle("품질") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20))

base2 + geom_bar(aes(x = quality), stat="count",
                 fill = "green", col= "black") +
  ggtitle("type별 품질") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20)) +
  facet_grid(type ~ .)
# 품질의 3,4,8,9의 관측치가 적다.
# 따라서 quality를 3개의 범주로 만든다.

# -- 고정산도 --
base2 + geom_histogram(aes(x = fixed, y = ..density..), bins = 30,
                       fill = "green", col= "black") +
  geom_line(aes(x=fixed),stat = "density", col="red", size = 1.5) +
  ggtitle("고정산도 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20))

base2 + geom_histogram(aes(x = fixed, y = ..density..), bins = 30,
                       fill = "green", col= "black") +
  geom_line(aes(x=fixed),stat = "density", col="red", size = 1.5) +
  ggtitle("type별 고정산도 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20)) +
  facet_grid(type ~ .)

base2 + geom_boxplot(aes(x = quality_g, y=fixed, fill=quality_g)) +
  ggtitle("품질별 고정산도 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20))

# -- 휘발성 산도 --
base2 + geom_histogram(aes(x = volatile, y = ..density..), bins = 30,
                       fill = "green", col= "black") +
  geom_line(aes(x=volatile),stat = "density", col="red", size = 1.5) +
  ggtitle("휘발성 산도 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20))

base2 + geom_histogram(aes(x = volatile, y = ..density..), bins = 30,
                       fill = "green", col= "black") +
  geom_line(aes(x=volatile),stat = "density", col="red", size = 1.5) +
  ggtitle("type별 휘발성 산도 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20)) +
  facet_grid(type ~ .)

base2 + geom_boxplot(aes(x = quality_g, y=volatile, fill=quality_g)) +
  ggtitle("품질별 휘발성 산도 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20))

# -- 구연산 --
base2 + geom_histogram(aes(x = citric, y = ..density..), bins = 30,
                       fill = "green", col= "black") +
  geom_line(aes(x=citric),stat = "density", col="red", size = 1.5) +
  ggtitle("구연산 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20))

base2 + geom_histogram(aes(x = citric, y = ..density..), bins = 30,
                       fill = "green", col= "black") +
  geom_line(aes(x=citric),stat = "density", col="red", size = 1.5) +
  ggtitle("type별 구연산 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20)) +
  facet_grid(type ~ .)

base2 + geom_boxplot(aes(x = quality_g, y=citric, fill=quality_g)) +
  ggtitle("품질별 구연산 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20))


# -- 잔류 설탕 --
base2 + geom_histogram(aes(x = sugar, y = ..density..), bins = 30,
                       fill = "green", col= "black") +
  geom_line(aes(x=sugar),stat = "density", col="red", size = 1.5) +
  ggtitle("잔류 설탕 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20))

base2 + geom_histogram(aes(x = sugar, y = ..density..), bins = 30,
                       fill = "green", col= "black") +
  geom_line(aes(x=sugar),stat = "density", col="red", size = 1.5) +
  ggtitle("type별 잔류 설탕 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20)) +
  facet_grid(type ~ .)

base2 + geom_boxplot(aes(x = quality_g, y=sugar, fill=quality_g)) +
  ggtitle("품질별 잔류 설탕 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20))

# -- 염화물 --
base2 + geom_histogram(aes(x = chlorides, y = ..density..), bins = 30,
                       fill = "green", col= "black") +
  geom_line(aes(x=chlorides),stat = "density", col="red", size = 1.5) +
  ggtitle("염화물 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20))

base2 + geom_histogram(aes(x = chlorides, y = ..density..), bins = 30,
                       fill = "green", col= "black") +
  geom_line(aes(x=chlorides),stat = "density", col="red", size = 1.5) +
  ggtitle("type별 염화물 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20)) +
  facet_grid(type ~ .)

base2 + geom_boxplot(aes(x = quality_g, y=chlorides, fill=quality_g)) +
  ggtitle("품질별 염화물 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20))


# -- 이산화황 --
base2 + geom_histogram(aes(x = sd, y = ..density..), bins = 30,
                       fill = "green", col= "black") +
  geom_line(aes(x=sd),stat = "density", col="red", size = 1.5) +
  ggtitle("이산화황 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20))

base2 + geom_histogram(aes(x = sd, y = ..density..), bins = 30,
                       fill = "green", col= "black") +
  geom_line(aes(x=sd),stat = "density", col="red", size = 1.5) +
  ggtitle("type별 자유 이산화황 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20)) +
  facet_grid(type ~ .)

base2 + geom_boxplot(aes(x = quality_g, y=sd, fill=quality_g)) +
  ggtitle("품질별 이산화황 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20))

# -- 산도 --
base2 + geom_histogram(aes(x = ph, y = ..density..), bins = 30,
                       fill = "green", col= "black") +
  geom_line(aes(x=ph),stat = "density", col="red", size = 1.5) +
  ggtitle("산도 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20))

base2 + geom_histogram(aes(x = ph, y = ..density..), bins = 30,
                       fill = "green", col= "black") +
  geom_line(aes(x=ph),stat = "density", col="red", size = 1.5) +
  ggtitle("type별 산도 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20)) +
  facet_grid(type ~ .)

base2 + geom_boxplot(aes(x = quality_g, y=ph, fill=quality_g)) +
  ggtitle("품질별 산도 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20))

# -- 황산염 --
base2 + geom_histogram(aes(x = sulphates, y = ..density..), bins = 30,
                       fill = "green", col= "black") +
  geom_line(aes(x=sulphates),stat = "density", col="red", size = 1.5) +
  ggtitle("황산염 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20))

base2 + geom_histogram(aes(x = sulphates, y = ..density..), bins = 30,
                       fill = "green", col= "black") +
  geom_line(aes(x=sulphates),stat = "density", col="red", size = 1.5) +
  ggtitle("type별 황산염 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20)) +
  facet_grid(type ~ .)

base2 + geom_boxplot(aes(x = quality_g, y=sulphates, fill=quality_g)) +
  ggtitle("품질별 황산염 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20))

# -- 알콜 --
base2 + geom_histogram(aes(x = alcohol , y = ..density..), bins = 30,
                       fill = "green", col= "black") +
  geom_line(aes(x=alcohol ),stat = "density", col="red", size = 1.5) +
  ggtitle("알콜 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20))

base2 + geom_histogram(aes(x = alcohol , y = ..density..), bins = 30,
                       fill = "green", col= "black") +
  geom_line(aes(x=alcohol ),stat = "density", col="red", size = 1.5) +
  ggtitle("type별 알콜 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20)) +
  facet_grid(type ~ .)

base2 + geom_boxplot(aes(x = quality_g, y=alcohol , fill=quality_g)) +
  ggtitle("품질별 알콜 정규화") +
  theme(plot.title = element_text(hjust= 0.5, vjust = 1, size =20))


# -------- 2) 군집분석 --------
# 군집분석을 하여 어떠한 관측치들이 이상치인지 확인한다.
rm(list = setdiff(ls(), c("con","wine","train2","test2","train", "test")))
# 군집분석은 train2의 데이터를 이용하며
# fixed, volatile, citric, sugar, chlorides, fsd, tsd, density, ph, 
# sulphates, alcohol을 이용하여 군집을 형성한다.


# -- k중심 군집분석 --
# 최소군집의 개수는 3개(상급,중급,하급)로 한다. 
# 최대의 군집의 개수는 11개(품질의 개수)로 한다.
k_mean <- function(x,data){
  model <- kmeans(data,centers = x,iter.max = 500)
  result <- with(model,c("g_in"=tot.withinss/totss, 
                         "g_out"=betweenss/totss))
  return(result)
}
set.seed(20190724)
result <- sapply(X = 2:40, FUN= k_mean, data= train2 %>% 
                   select(-c(type,quality,quality_g)))
result <- as.data.frame(t(result))
# 군집내의 거리의 그래프
ggplot(result,
       aes(x=2:40,y=g_in)) +
  geom_point(colour = "blue", size = 5) +
  geom_line(colour = "red") +
  scale_x_continuous(breaks = 2:40) +
  ggtitle("군집내 거리") +
  theme(plot.title = element_text(hjust=0.5, vjust=1,
                                  size = 25, colour = "red"))

# 군집간의 거리의 그래프
ggplot(result,
       aes(x=2:40,y=g_out)) +
  geom_point(colour = "blue", size = 5) +
  geom_line(colour = "red") +
  scale_x_continuous(breaks = 2:40) +
  ggtitle("군집간 거리") +
  theme(plot.title = element_text(hjust=0.5, vjust=1,
                                  size = 25, colour = "red"))
# 군집의 개수는 35개가 적당해 보인다.
clust <- kmeans(train2 %>% select(-c(quality,type,quality_g)), centers = 35,
                iter.max = 200)
clust
with(clust, c(tot.withinss/totss, betweenss/totss))
# 군집내에서 quality가 여러종류 썪여 있으면 이상치로 간주하고 제거한다.
train2 %>% group_by(clust$cluster) %>% summarise("하급" = sum(quality_g=="하급"),
                                          "중급" = sum(quality_g=="중급"),
                                          "상급" = sum(quality_g=="상급")) %>% 
  as.data.frame
# 중급이 너무많아 군집화가 의미가 없다고 판단, 군집화를 하지 않는다.

# ---- 자기조직화지도(SOM) ----
som_model <- som(train2 %>% select(-c(type,quality,quality_g)) %>% as.matrix)
plot(som_model)

names(som_model)
som_model$unit.classif

train2 %>% group_by(som_model$unit.classif) %>% summarise("하급" = sum(quality_g=="하급"),
                                           "중급" = sum(quality_g=="중급"),
                                           "상급" = sum(quality_g=="상급")) %>% 
  as.data.frame
# kmeas 군집분석과 마찬가지로 모든 군집에서 중급의 값이 너무 많다.
# 따라서, SOM도 사용하지 않는다.

# ---- 주성분 분석 ----
prc <- prcomp(wine %>% select(-c(type, quality, quality_g)),
                scale = TRUE, retx = TRUE)
summary(prc)
# Proportion of Variance는 분산의 설명력이며 누적값이 0,7~0.9의 값을 선택한다.
#PC6까지 사용한다

prc$x # 주성분 점수 : 새로운 변수로 사용
prc$rotation 
# 주성분 계수로 값의 절대값으로 
# 새로운 변수가 어떠한 변수인지 이름을 붙일 때 사용한다.

newdata <- cbind(wine,prc$x) %>% tbl_df %>% 
  select(type, quality_g, quality,PC1, PC2, PC3, PC4, PC5, PC6)
set.seed(20190724)
newTrain <- newdata %>% group_by(type,quality_g) %>% 
  sample_frac(0.7) %>% group_by()
newTest <- anti_join(newdata,newTrain)
# 각 변수가 독립이라 가정하여 사용하지 않는다.

# -------------------------------------------------------------------------------- #
#
#                         ---- 2. 데이터 분석(quality 예측) ----
#
# -------------------------------------------------------------------------------- #
rm(list = setdiff(ls(),c("con","wine","train2","test2",
                         "train", "test","newdata","newTrain",
                         "newTest","select") ))

# ---- 1) MLP(train2 : quality예측) ----


# 다층 퍼셉드로은 정규화를 해야 정확한 값을 구할 수 있다.
# 따라서 train2를 사용한다.
# quality를 먼저 예측한후 quality_g로 바꾼어 예측율을 검사한다.
net <- function(x, data){
  nnet(quality ~ . -quality_g, data=data,
       size = x)
}

set.seed(123456)
# model <- lapply(2:30,FUN = net, data=train2) # 정규화를 한 데이터
# names(model) <- 2:30

# 주성분 분석을 한 데이터
set.seed(123456)
model2 <- lapply(2:30, FUN = net, data=newTrain)
names(model2) <- 2:30

# quality를 quality_g로 변경하는 함수
lv <- function(x){ 
  ifelse(x %in% c("1","2","3","4"),"하급",
         ifelse(x %in% c("5","6","7"), "중급", "상급")) %>% 
    factor(levels=c("하급","중급","상급"))
}


# pred <- lapply(model, FUN = function(x){
#   predict(x, test2, type = "class") %>% lv
# })

pred2 <- lapply(model2, FUN = function(x){
  predict(x, newTest, type = "class") %>% lv
})



# kappa <- sapply(pred, function(x){
#   confusionMatrix(x, test2$quality_g)$overall["Kappa"]
# })
kappa2 <- sapply(pred2, function(x){
  confusionMatrix(x, newTest$quality_g)$overall["Kappa"]
})



# plot(x = 2:30, y = kappa, type= "l")
which.max(kappa) # size = 28일때 Kappa값이 가장 크다.
plot(x = 2:30, y = kappa2, type= "l")
which.max(kappa2) # size = 14일때 Kappa값이 가장 크다.



# result <- lapply(pred, function(x){
#   confusionMatrix(x, test2$quality_g)
# })
result2 <- lapply(pred2, function(x){
  confusionMatrix(x, newTest$quality_g)
})



# result$'28' # 주성분 분석한 것보다 더 좋게 나온다.
result2$'28'
# 기존의 변수로 분석을 하는데 하급과 상급의 데이터가 부족하여 
# 제대로 분석을 하지 못한다고 판단된다. 따라서 새로운 변수가 
# 추가되거나 새로운 데이터가 더 필요할 것으로 생각된다.\

# -- size = 29인 변수를 선택 --
model <- model2$"28"

summary(model) # 모형 요약

plotnet(model) # 시각화

# ------ SVM -------
# 모델링을 위해서 타겟변수만 factor처리 및 다른 변수는 모두 연속형이거나 순서형의 범주형 변수로 가정

# # kernel에 따른 조정인자 튜닝
# # 1.방사형 커널
result <- tune.svm(quality ~ . -quality_g, data = train2, gamma = 2^(-5:0), cost = 2^(0:4), kernel = "radial")

# # 2.서포트 벡터 분류기 (직선)
result1 <- tune.svm(quality ~ . -quality_g, data = train2, cost = 2^(0:4), kernel = "linear")

# # 3.다항식 커널 (곡선)
result2 <- tune.svm(quality ~ . -quality_g, data = train2, cost = 2^(0:4), degree = 2:4, kernel = "polynomia")
#  # cost 랑 gamma:범위를 지정한거임 범위 내에 모형들을 만들어줘서, random 으로 바꾸든가, 범위를 지정하는 동 해라. degree=차수

# 적정 cost,gamma값 확인
result$best.parameters # gamma = 1, cost = 4
result1$best.parameters # cost = 1
result2$best.parameters # degree = 4, cost = 8

# -- train1의 결과 --
# > result$best.parameters
# gamma cost
# 12     1    2
# > result1$best.parameters
# cost
# 1    1
# > result2$best.parameters
# degree cost
# 2      3    1

# SVM모델링 수행(kernel인자에 raial입력으로 방사커 널 수행) -gamma와 cost인자 설정
wine_svm <- svm(quality ~ . -quality_g, data = train2, gamma = 1, cost = 4, kernel = "radial")

# kernel인자에 linear입력으로 서포트 벡터 분류기 수행 - cost인자 설정
wine_svm1 <- svm(quality ~ .-quality_g, data = train, cost = 1, kernel = "linear")

# kernel인자에 polynomia입력으로 다차원 커널의 SVM수행 - cost, degree인자 설정
wine_svm2 <- svm(quality ~ .-quality_g, data = train, cost =8 , degree = 4, kernel = "polynomia")

# 결과확인
summary(wine_svm)
summary(wine_svm1)
summary(wine_svm2)

# 세 경우의 서포트 벡터 확인(몇 번째 관찰값이 서포트 벡터인지 확인)
wine_svm$index
wine_svm1$index
wine_svm2$index

# 세 경우의 정확도 측정(처음 분리했던 test데이터 이용)
wine_svm_predict <- predict(wine_svm, test) %>% lv
wine_svm1_predict1 <- predict(wine_svm1, test) %>% lv
wine_svm2_predict2 <- predict(wine_svm2, test) %>% lv

# 정확도를 표로 시각화하기
confusionMatrix(wine_svm_predict, test$quality_g)
confusionMatrix(wine_svm1_predict1, test$quality_g)
confusionMatrix(wine_svm2_predict2, test$quality_g) # 가장 kappa값이 높다.

# ---- 의사결정나무 ----
set.seed(20190724)
tree <- rpart(quality ~ ., data=newTrain %>% select(-quality_g),
              cp = -1, method = "class")

# -- 최대 성장 모형 --
plot(tree)
text(tree)

# -- cp --
index <- which.min(tree$cptable[,"xerror"])
cp <- tree$cptable[index,"CP"]

# -- 가지치기 --
tree <- prune(tree, cp = cp)

#-- 그림 --
plot(tree, margin = 0.01, compress = TRUE,uniform = TRUE)
text(tree, cex = 0.8)
tree

# -- 변수 중요도 --
barplot(sort(tree$variable.importance, decreasing = TRUE),
        main = "변수중요도", cex.main = 3)

# -- 예측 -- 
pred <- predict(tree, newTest, type = "class") %>% lv
confusionMatrix(pred,test$quality_g)

# ---- 나이브 베이즈 분류기 ----

select <- dplyr::select
model <- NaiveBayes(quality ~ ., train2 %>% select(-quality_g), fL= 1) 
# 라플라스 추정량을 1로 둔다.
pred <- predict(model, test2, threshold = 0.1)$class %>% lv
confusionMatrix(pred,test2$quality_g)

k <- function(x){
  data <- train2 %>% select(-c("quality_g",x))
  m <- NaiveBayes(quality ~ ., data=data, fL= 1) 
  # 라플라스 추정량을 1로 둔다.
  print(m$varnames)
  p <- predict(m, test2, threshold = 0.1)$class %>% lv
  confusionMatrix(p,test2$quality_g)
  
}

names(train2)
k("type") # Accuracy = 0.9016, Kappa = 0.1204
k("fixed") # Accuracy = 0.9023, Kappa = 0.1264
k("volatile") # Accuracy = 0.9009, Kappa = -0.0024
k("citric") # Accuracy = 0.9037, Kappa = 0.1387
k("sugar") # Accuracy = 0.9037, Kappa = 0.1522
k("chlorides") # Accuracy = 0.9132, Kappa = 0.1847
k("ph") # Accuracy = 0.8996, Kappa = 0.1255
k("sd") # Accuracy = 0.9023, Kappa = 0.1309
k("sulphates") # Accuracy = 0.905, Kappa = 0.1368
k("alcohol") # Accuracy = 0.8982, Kappa = 0.1404

k(c("chlorides","sugar")) # Accuracy = 0.9111, Kappa = 0.1702
k(c("chlorides","sugar","alcohol")) # Accuracy = 0.9111, Kappa = 0.1794
k(c("chlorides","sugar","alcohol","citric")) # Accuracy = 0.9125, Kappa = 0.1737
k(c("chlorides","sugar","alcohol","citric","sulphates")) # Accuracy = 0.9118, Kappa = 0.0.143
# volatile - 가장 영향이 큼
# chlorides - 가장 영향이 작음

'데이터 마이닝' 카테고리의 다른 글

모형의 평가방법( 예측모형)  (0) 2019.08.29
Kaggle 대회 데이터 분석  (0) 2019.08.28
머신러닝 시작  (0) 2019.08.09
통계상담과제  (0) 2019.07.22
Pulse 분석  (0) 2019.07.22