상관분석과 단순 회귀분석

상관분석
단순 회귀분석
상관계수
결정계수
공개

2026-07-06

상관분석은 두 변수 간의 관계 강도와 방향을 측정하고, 단순 회귀분석은 한 변수(독립 변수)를 사용해 다른 변수(종속 변수)를 예측하는 모형으로 상관분석은 두 변수 간의 관계 강도와 방향을 측정하는 데 중점을 두고, 회귀분석은 한 변수를 사용해 다른 변수를 예측하는 데 중점을 둔다. 특히 상관계수의 제곱은 회귀 분석에서 결정계수로 해석된다.

#| label: shinylive-reg-simple
#| viewerHeight: 700
#| standalone: true

library(shiny)
library(showtext)
showtext_auto()

library(bslib)
library(showtext)
tryCatch(sysfonts::font_add_google("Nanum Myeongjo", "kr"), error = function(e) NULL)
showtext_auto()

# ── Tufte 팔레트 · 테마 (자동 주입) ──────────────────────────
bit_cream <- "#fffff8"; bit_ink <- "#111111"; bit_rust <- "#8a1500"
bit_muted <- "#4a4a44"; bit_grid <- "#e8e6dc"; bit_axis <- "#8a8578"
theme_tufte_bit <- function(base_size = 13) {
  ggplot2::theme_minimal(base_size = base_size) +
    ggplot2::theme(
      text = ggplot2::element_text(family = "kr", colour = bit_ink),
      plot.title = ggplot2::element_text(family = "kr", size = base_size, hjust = 0),
      plot.background = ggplot2::element_rect(fill = bit_cream, colour = NA),
      panel.background = ggplot2::element_rect(fill = bit_cream, colour = NA),
      panel.grid.major = ggplot2::element_line(colour = bit_grid, linewidth = 0.3),
      panel.grid.minor = ggplot2::element_blank(),
      axis.line = ggplot2::element_line(colour = bit_axis, linewidth = 0.3),
      axis.ticks = ggplot2::element_line(colour = bit_axis, linewidth = 0.3)
    )
}
if (requireNamespace("ggplot2", quietly = TRUE)) ggplot2::theme_set(theme_tufte_bit())
bit_theme <- bs_theme(
  version = 5, bg = bit_cream, fg = bit_ink, primary = bit_rust,
  base_font = font_collection("Palatino Linotype", "Georgia", "Times New Roman", "serif"),
  "card-box-shadow" = "none"
)
# ─────────────────────────────────────────────────────────────

ui <- fluidPage(
  theme = bit_theme,
  titlePanel("상관분석과 단순 회귀분석"),

  sidebarLayout(
    sidebarPanel(
      fileInput("file", "CSV 파일 업로드", accept = c("text/csv", "text/comma-separated-values,text/plain", ".csv")),
      radioButtons("dataset", "데이터셋 선택:",
                   choices = c("mtcars", "USArrests", "업로드 데이터셋"),
                   selected = "mtcars"),
      selectInput("y_var", "Y 변수 (종속변수):", ""),
      selectInput("x_var", "X 변수 (독립변수):", "")
    ),

    mainPanel(
      tabsetPanel(
        tabPanel("산점도", plotOutput("scatterplot")),
        tabPanel("상관계수",
                 verbatimTextOutput("correlation"),
                 verbatimTextOutput("cor_test")),
        tabPanel("회귀분석", verbatimTextOutput("regression"))
      )
    )
  )
)

server <- function(input, output, session) {

  data <- reactive({
    if (input$dataset == "업로드 데이터셋") {
      req(input$file)
      read.csv(input$file$datapath, header = TRUE)
    } else {
      switch(input$dataset,
             "mtcars" = mtcars,
             "USArrests" = USArrests)
    }
  })

  observe({
    choices <- names(data())[sapply(data(), is.numeric)]
    updateSelectInput(session, "y_var", choices = choices)
    updateSelectInput(session, "x_var", choices = choices)
  })

  output$scatterplot <- renderPlot({
    req(input$y_var, input$x_var)
    plot(data()[[input$x_var]], data()[[input$y_var]],
         xlab = input$x_var, ylab = input$y_var,
         main = "회귀선이 포함된 산점도")
    abline(lm(data()[[input$y_var]] ~ data()[[input$x_var]]), col = "#8a1500", lwd = 2)
    legend("topleft", legend = "회귀선", col = "#8a1500", lwd = 2, bty = "n")
  })

  output$correlation <- renderPrint({
    req(input$y_var, input$x_var)
    cor_val <- cor(data()[[input$x_var]], data()[[input$y_var]])
    det_coef <- cor_val^2
    cat("상관계수:", round(cor_val, 3), "\n")
    cat("결정계수 (R-squared):", round(det_coef, 3))
  })

  output$cor_test <- renderPrint({
    req(input$y_var, input$x_var)
    cor.test(data()[[input$x_var]], data()[[input$y_var]])
  })

  output$regression <- renderPrint({
    req(input$y_var, input$x_var)
    lm_model <- lm(data()[[input$y_var]] ~ data()[[input$x_var]])
    names(lm_model$coefficients) <- c("절편", input$x_var)
    summary(lm_model)
  })

}

shinyApp(ui, server)

라이센스