# 훈련 데이터와 테스트 데이터로 분리
set.seed(1)
k <- createDataPartition(movie$장르, p=0.8, list=F)
train_data <- movie[k, ]
test_data <- movie[-k, ]
nrow(train_data)
# 나이브 베이즈 모델 생성
library(e1071)
library(naivebayes)
new_model <- naive_bayes( 장르~ .,data=train_data, laplace = 1)
# 나이 순서 조정
age_choices <- sort(unique(movie$나이), decreasing = FALSE)
age_choices
# UI 정의
ui <- fluidPage(
tags$head(
tags$style(HTML("
@import url('//fonts.googleapis.com/css?family=Lobster|Cabin:400,700');
h1 {
font-family: 'Lobster', cursive;
font-weight: 500;
line-height: 1.1;
color: #FD748C;
}
body {
background-color: #FDDDCD;
}
"))
),
headerPanel("Movie Genre Predictor"),
sidebarLayout(
sidebarPanel(
radioButtons("age", "나이", choices = age_choices),
radioButtons("gender", "성별", choices = unique(movie$성별)),
selectInput("job", "직업", choices = unique(movie$직업)),
selectInput("married", "결혼여부", choices = unique(movie$결혼여부)),
selectInput("relationship", "이성친구 여부", choices = unique(movie$이성친구)),
actionButton("predict", "예측하기", style = "color: #FFF; background-color: #FF9999;"),
actionButton("reset","Reset", style = "color: #FFF; background-color: #FF9999;")
),
mainPanel(
verbatimTextOutput("prediction"),
plotOutput("prob_plot")
)
)
)
# 서버 로직 정의
server <- function(input, output, session) {
result <- reactiveVal(NULL)
observeEvent(input$predict, {
test_data <- data.frame(
나이 = input$age,
성별 = input$gender,
직업 = input$job,
결혼여부 = input$married,
이성친구 = input$relationship
)
prediction_result <- predict(new_model, test_data, type = "prob")
predicted_genre <- colnames(prediction_result)[which.max(prediction_result)]
output$prediction <- renderPrint({
paste("예측 결과: ", predicted_genre, sprintf("%.2f%%", max(prediction_result) * 100))
})
result(prediction_result)
})
output$prob_plot <- renderPlot({
req(result())
prob_data <- as.data.frame(t(result()))
prob_data$장르 <- rownames(prob_data)
prob_data$확률 <- prob_data$V1 * 100
# 최대값에 해당하는 장르를 확인
max_genre <- prob_data$장르[which.max(prob_data$확률)]
ggplot(prob_data, aes(x = 장르, y = 확률)) +
geom_bar(stat = "identity", aes(fill = 장르 == max_genre), width = 0.5) +
scale_fill_manual(values = c("TRUE" = "#FF9999", "FALSE" = "gray")) +
geom_text(aes(label = sprintf("%.2f%%", 확률)), vjust = -0.5, size = 4) +
labs(title = "장르별 확률", x = "장르", y = "확률 (%)") +
theme_minimal() +
theme(legend.position = "none") # 범례 제거
})
observeEvent(input$reset, {
updateRadioButtons(session, "age", selected = character(0))
updateRadioButtons(session, "gender", selected = character(0))
updateSelectInput(session, "job", selected = "")
updateSelectInput(session, "married", selected = "")
updateSelectInput(session, "relationship", selected = "")
output$prediction <- renderPrint({
"조건을 선택하세요"
})
result(NULL) # result를 초기화하여 플롯을 지웁니다.
})
}
# Shiny 앱 실행
shinyApp(ui = ui, server = server)