이표본 평균차이 검정

평균 검정
단일 표본 t-검정
대응 표본 t-검정
독립 표본 t-검정
저자

이광춘

공개

2024-05-17

2표본 t-검정은 두 독립적인 그룹의 평균 차이가 통계적으로 유의미한지를 판단하기 위한 통계적 검정 방법이다. 이 검정은 두 집단이 정규분포를 따르고, 데이터가 독립적인 경우에 사용할 수 있다.

검정을 수행할 때 두 그룹의 분산이 같은지 다른지에 따라 검정 방법이 달라진다. 분산이 같다고 가정할 경우 등분산을 가정하는 t-검정을 사용하고, 분산이 다르다고 가정할 경우 등분산이 아닌 t-검정을 사용한다. R에서는 t.test() 함수를 사용하여 이 두 경우를 쉽게 계산할 수 있다. var.equal = TRUE 옵션을 사용하면 등분산을 가정하는 t-검정을 수행하고, var.equal = FALSE 옵션을 사용하면 등분산이 아닌 t-검정을 수행한다.

1 Shiny 앱

#| label: shinylive-prob-law
#| viewerWidth: 800
#| viewerHeight: 600
#| standalone: true

library(ggplot2)
library(showtext)
library(gt)
# font_add_google(name = "Nanum Gothic", regular.wt = 400)
showtext_auto()

# 3. 2-표본 t-검정---------------
t.test3 <- function(x, y, V1, V2, m0 = 0, alpha = 0.05, alternative = "two.sided") {
  M1 <- mean(x)
  M2 <- mean(y)
  n1 <- length(x)
  n2 <- length(y)
  sigma1 <- sqrt(V1)
  sigma2 <- sqrt(V2)
  S <- sqrt((V1 / n1) + (V2 / n2))
  statistic <- (M1 - M2 - m0) / S
  p <- if (alternative == "two.sided") {
    2 * pnorm(abs(statistic), lower.tail = FALSE)
  } else if (alternative == "less") {
    pnorm(statistic, lower.tail = TRUE)
  } else {
    pnorm(statistic, lower.tail = FALSE)
  }
  # p <- (1 - pnorm((M-m0)/S))
  LCL <- (M1 - M2 - S * qnorm(1 - alpha / 2))
  UCL <- (M1 - M2 + S * qnorm(1 - alpha / 2))
  value <- list(mean1 = M1, mean2 = M2, m0 = m0, sigma1 = sigma1, sigma2 = sigma2, S = S, statistic = statistic, p.value = p, LCL = LCL, UCL = UCL, alternative = alternative)
  # print(sprintf("P-value = %g",p))
  # print(sprintf("Lower %.2f%% Confidence Limit = %g",
  #               alpha, LCL))
  # print(sprintf("Upper %.2f%% Confidence Limit = %g",
  #               alpha, UCL))
  return(value)
}

two_means_UI <- function(id) {

  ns <- NS(id)

  # 1. 메인 패널 ------------------------------------
  mainPanel <- mainPanel(
    tabsetPanel(
      tabPanel("검정 결과", uiOutput(ns("results_twomean"))),
      tabPanel("시각화", plotOutput(ns("plot_twomean"))),
      tabPanel("데이터", gt_output(ns("table_twomean")))
    )
  )

  # 2. 옆 패널 --------------------------------------
  sidebarPanel <- sidebarPanel(width = 4,

     tags$br(),
     tags$h4("* 데이터"),

     textInput(ns("twomeans_sample1"), "표본 1", value = "0.9, -0.8, 0.1, -0.3, 0.2"),
     textInput(ns("twomeans_sample2"), "표본 2", value = "0.8, -0.9, -0.1, 0.4, 0.1"),

     tags$p("※ 콤마로 구분된 숫자 입력. ex) 7.2, 4.7, 5.03, 등"),


     tags$p("모집단 분산"),
     radioButtons(
       inputId = ns("twomeans_var.equal"),
       label = "분산에 대한 가정:",
       choices = c(
         "\\( \\sigma^2_1 = \\sigma^2_2 \\)" = TRUE,
         "\\( \\sigma^2_1 \\neq \\sigma^2_2 \\)" = FALSE
       )
     ),

     checkboxInput(ns("twomeans_popsd"), "모집단 분산을 알는 경우:", FALSE),
     conditionalPanel(
       # condition = "input.twomeans_popsd == 1",
       condition = paste0("input['", ns("twomeans_popsd"), "'] == 1"),
       numericInput(ns("twomeans_sigma21"), "\\(\\sigma^2_1 = \\)",
                    value = 1, min = 0, step = 1, width = "100px"
       ),
       numericInput(ns("twomeans_sigma22"), "\\(\\sigma^2_2 = \\)",
                    value = 1, min = 0, step = 1, width = "100px"
       )
     ),


     tags$h4("* 가설검정"),

     tags$p("1. 귀무가설"),
     tags$p("\\( H_0 : \\mu_1 - \\mu_2 = \\)"),

     numericInput(ns("twomeans_h0"),
                  label = NULL,
                  value = 0, step = 0.1, width="100px"),

     tags$p("2. 검정방향"),
     radioButtons(
       inputId = ns("twomeans_alternative"),
       label = "대립가설",
       inline = TRUE,
       choices = c(
         "\\( \\neq \\)" = "two.sided",
         "\\( > \\)" = "greater",
         "\\( < \\)" = "less"
       )
     ),


     tags$p("3. 유의수준"),
     sliderInput(ns("twomeans_alpha"),
                 "유의수준 \\(\\alpha = \\)",
                 min = 0.01,
                 max = 0.10,
                 step = 0.01,
                 value = 0.05
     )

  )

  # 3. 레이아웃 -----------------------------------------------------------
  tagList(
    withMathJax(),
    tags$div(

      fluidPage(
        theme = shinythemes::shinytheme("flatly"),

        sidebarPanel,
        mainPanel
      )
    )
  )
}



two_means_server <- function(id) {
  moduleServer(id, function(input, output, session) {

    output$results_twomean <- renderUI({

      dat1 <- as.numeric(unlist(strsplit(input$twomeans_sample1, ",")))
      dat2 <- as.numeric(unlist(strsplit(input$twomeans_sample2, ",")))

      if (anyNA(dat1) | length(dat1) < 2 | anyNA(dat2) | length(dat2) < 2) {
        "Invalid input or not enough observations"
      } else if ( input$twomeans_popsd == FALSE & input$twomeans_var.equal == TRUE ){
        test_confint <- t.test(x = dat1, y = dat2, mu = input$twomeans_h0, alternative = "two.sided", conf.level = 1 - input$twomeans_alpha, paired = FALSE, var.equal = TRUE)
        test <- t.test(x = dat1, y = dat2, mu = input$twomeans_h0, alternative = input$twomeans_alternative, conf.level = 1 - input$twomeans_alpha, paired = FALSE, var.equal = TRUE)
        s_p <- sqrt(((length(dat1) - 1) * var(dat1) + (length(dat2) - 1) * var(dat2)) / test_confint$parameter)
        withMathJax(
          tags$h2("데이터"),
          br(),
          paste(c("\\(표본_1=\\)", paste(dat1, collapse = ", ")), collapse = " "),
          br(),
          paste(c("\\(표본_2=\\)", paste(dat2, collapse = ", ")), collapse = " "),
          br(),
          paste0("\\(n_1 =\\) ", length(dat1)),
          br(),
          paste0("\\(n_2 =\\) ", length(dat2)),
          br(),
          paste0("\\(\\bar{x}_1 =\\) ", round(mean(dat1), 3)),
          br(),
          paste0("\\(\\bar{x}_2 =\\) ", round(mean(dat2), 3)),
          br(),
          paste0("\\(s^2_1 =\\) ", round(var(dat1), 3)),
          br(),
          paste0("\\(s^2_2 =\\) ", round(var(dat2), 3)),
          br(),
          br(),
          tags$h2("신뢰구간 - 양측"),
          br(),
          paste0((1 - input$twomeans_alpha) * 100, "% CI 신뢰구간: \\(\\mu_1 - \\mu_2 = \\bar{x}_1 - \\bar{x}_2 \\pm t_{\\alpha/2, n_1 + n_2 - 2} (s_p) \\sqrt{\\dfrac{1}{n_1} + \\dfrac{1}{n_2}} \\)"),
          br(),
          paste0("where ", "\\( s_p = \\sqrt{\\dfrac{(n_1 - 1)s^2_1 + (n_2 - 1)s^2_2}{n_1 + n_2 - 2}} = \\) ", round(s_p, 3)),
          br(),
          br(),
          paste0(
            "\\( \\Rightarrow \\)", (1 - input$twomeans_alpha) * 100, "% CI 신뢰구간: \\(\\mu_1 - \\mu_2 = \\) ", round(test_confint$estimate[1], 3), ifelse(test_confint$estimate[2] >= 0, paste0(" - ", round(test_confint$estimate[2], 3)), paste0(" + ", round(abs(test_confint$estimate[2]), 3))), " \\( \\pm \\) ", "\\( (\\)", round(qt(input$twomeans_alpha / 2, df = test_confint$parameter, lower.tail = FALSE), 3), " * ", round(s_p, 3), " * ", round(sqrt(1 / length(dat1) + 1 / length(dat2)), 3), "\\( ) \\) ", "\\( = \\) ",
            "[", round(test_confint$conf.int[1], 3), "; ", round(test_confint$conf.int[2], 3), "]"
          ),
          br(),
          br(),
          tags$h2("가설 검정"),
          br(),
          paste0("1. \\(H_0 : \\mu_1 - \\mu_2 = \\) ", test$null.value, " and \\(H_1 : \\mu_1 - \\mu_2 \\) ", ifelse(input$twomeans_alternative == "two.sided", "\\( \\neq \\) ", ifelse(input$twomeans_alternative == "greater", "\\( > \\) ", "\\( < \\) ")), test$null.value),
          br(),
          paste0(
            "2. 검정 통계량 : \\(t_{obs} = \\dfrac{(\\bar{x}_1 - \\bar{x}_2) - (\\mu_1 - \\mu_2)}{s_p \\sqrt{\\dfrac{1}{n_1} + \\dfrac{1}{n_2}}} = \\) ",
            "(", round(test$estimate[1], 3), ifelse(test$estimate[2] >= 0, paste0(" - ", round(test$estimate[2], 3)), paste0(" + ", round(abs(test$estimate[2]), 3))), ifelse(test$null.value >= 0, paste0(" - ", test$null.value), paste0(" + ", abs(test$null.value))), ") / (", round(s_p, 3), " * ", round(sqrt((1 / length(dat1)) + (1 / length(dat2))), 3), ") \\( = \\) ",
            round(test$statistic, 3)
          ),
          br(),
          paste0(
            "3. 임계값 :", ifelse(input$twomeans_alternative == "two.sided", " \\( \\pm t_{\\alpha/2, n_1 + n_2 - 2} = \\pm t(\\)", ifelse(input$twomeans_alternative == "greater", " \\( t_{\\alpha, n_1 + n_2 - 2} = t(\\)", " \\( -t_{\\alpha, n_1 + n_2 - 2} = -t(\\)")),
            ifelse(input$twomeans_alternative == "two.sided", input$twomeans_alpha / 2, input$twomeans_alpha), ", ", test$parameter, "\\()\\)", " \\( = \\) ",
            ifelse(input$twomeans_alternative == "two.sided", "\\( \\pm \\)", ifelse(input$twomeans_alternative == "greater", "", " -")),
            ifelse(input$twomeans_alternative == "two.sided", round(qt(input$twomeans_alpha / 2, df = test$parameter, lower.tail = FALSE), 3), round(qt(input$twomeans_alpha, df = test$parameter, lower.tail = FALSE), 3))
          ),
          br(),
          paste0("4. 결론 : ", ifelse(test$p.value < input$twomeans_alpha, "\\(H_0\\) 기각.", "\\(H_0\\) 기각 못함")),
          br(),
          br(),
          tags$h2("해석"),
          br(),

          paste0( input$twomeans_alpha * 100, "% 유의수준에서, ",
                  "평균 차이가 ", test$null.value, " 이라는 귀무가설을 ",
                  ifelse(test$p.value < input$twomeans_alpha, "기각한다", "기각하지 않는다"),
                  " \\((p\\)-값 ", ifelse(test$p.value < 0.001, "< 0.001", paste0("\\(=\\) ", round(test$p.value, 3))), ")", ".")
        )
      } else if ( input$twomeans_popsd == FALSE & input$twomeans_var.equal == FALSE) {
        test_confint <- t.test(x = dat1, y = dat2, mu = input$twomeans_h0, alternative = "two.sided", conf.level = 1 - input$twomeans_alpha, paired = FALSE, var.equal = FALSE)
        test <- t.test(x = dat1, y = dat2, mu = input$twomeans_h0, alternative = input$twomeans_alternative, conf.level = 1 - input$twomeans_alpha, paired = FALSE, var.equal = FALSE)
        withMathJax(
          tags$h2("데이터"),
          br(),
          paste(c("\\(표본_1=\\)", paste(dat1, collapse = ", ")), collapse = " "),
          br(),
          paste(c("\\(표본_2=\\)", paste(dat2, collapse = ", ")), collapse = " "),
          br(),
          paste0("\\(n_1 =\\) ", length(dat1)),
          br(),
          paste0("\\(n_2 =\\) ", length(dat2)),
          br(),
          paste0("\\(\\bar{x}_1 =\\) ", round(mean(dat1), 3)),
          br(),
          paste0("\\(\\bar{x}_2 =\\) ", round(mean(dat2), 3)),
          br(),
          paste0("\\(s^2_1 =\\) ", round(var(dat1), 3)),
          br(),
          paste0("\\(s^2_2 =\\) ", round(var(dat2), 3)),
          br(),
          br(),
          tags$h2("신뢰구간 - 양측"),
          br(),
          paste0((1 - input$twomeans_alpha) * 100, "% CI 신뢰구간: \\(\\mu_1 - \\mu_2 = \\bar{x}_1 - \\bar{x}_2 \\pm t_{\\alpha/2, \\nu} \\sqrt{\\dfrac{s^2_1}{n_1} + \\dfrac{s^2_2}{n_2}} \\)"),
          br(),
          paste0("여기서, ", "\\( \\nu = \\dfrac{\\Bigg(\\dfrac{s^2_1}{n_1} + \\dfrac{s^2_2}{n_2}\\Bigg)^2}{\\dfrac{\\Bigg(\\dfrac{s^2_1}{n_1}\\Bigg)^2}{n_1-1} + \\dfrac{\\Bigg(\\dfrac{s^2_2}{n_2}\\Bigg)^2}{n_2-1}} = \\) ", round(test$parameter, 3)),
          br(),
          br(),
          paste0(
            "\\( \\Rightarrow \\)", (1 - input$twomeans_alpha) * 100, "% CI 신뢰구간: \\(\\mu_1 - \\mu_2 = \\) ", round(test_confint$estimate[1], 3), ifelse(test_confint$estimate[2] >= 0, paste0(" - ", round(test_confint$estimate[2], 3)), paste0(" + ", round(abs(test_confint$estimate[2]), 3))), " \\( \\pm \\) ", "\\( (\\)",round(qt(input$twomeans_alpha / 2, df = test_confint$parameter, lower.tail = FALSE), 3), " * ", round(test_confint$stderr, 3), "\\( ) \\) ", "\\( = \\) ",
            "[", round(test_confint$conf.int[1], 3), "; ", round(test_confint$conf.int[2], 3), "]"
          ),
          br(),
          br(),
          tags$em(paste0("주의: 자유도를 df = \\(min(n_1 - 1, n_2 - 1) \\) 으로 단순하게 근사화해서 구함, 그래서 이 경우에 df = ",
                         min(length(dat1) - 1, length(dat2) - 1), ".")),
          br(),
          br(),
          tags$h2("가설 검정"),
          br(),
          paste0("1. \\(H_0 : \\mu_1 - \\mu_2 = \\) ", test$null.value, " and \\(H_1 : \\mu_1 - \\mu_2 \\) ", ifelse(input$twomeans_alternative == "two.sided", "\\( \\neq \\) ", ifelse(input$twomeans_alternative == "greater", "\\( > \\) ", "\\( < \\) ")), test$null.value),
          br(),
          paste0(
            "2. 검정 통계량 : \\(t_{obs} = \\dfrac{(\\bar{x}_1 - \\bar{x}_2) - (\\mu_1 - \\mu_2)}{\\sqrt{\\dfrac{s^2_1}{n_1} + \\dfrac{s^2_2}{n_2}}} = \\) ",
            "(", round(test$estimate[1], 3), ifelse(test$estimate[2] >= 0, paste0(" - ", round(test$estimate[2], 3)), paste0(" + ", round(abs(test$estimate[2]), 3))), ifelse(test$null.value >= 0, paste0(" - ", test$null.value), paste0(" + ", abs(test$null.value))), ") / ", round(test$stderr, 3), " \\( = \\) ",
            round(test$statistic, 3)
          ),
          br(),
          paste0(
            "3. 임계값 :", ifelse(input$twomeans_alternative == "two.sided", " \\( \\pm t_{\\alpha/2, \\nu} = \\pm t(\\)", ifelse(input$twomeans_alternative == "greater", " \\( t_{\\alpha, \\nu} = t(\\)", " \\( -t_{\\alpha, \\nu} = -t(\\)")),
            ifelse(input$twomeans_alternative == "two.sided", input$twomeans_alpha / 2, input$twomeans_alpha), ", ", round(test$parameter, 3), "\\()\\)", " \\( = \\) ",
            ifelse(input$twomeans_alternative == "two.sided", "\\( \\pm \\)", ifelse(input$twomeans_alternative == "greater", "", " -")),
            ifelse(input$twomeans_alternative == "two.sided", round(qt(input$twomeans_alpha / 2, df = test$parameter, lower.tail = FALSE), 3), round(qt(input$twomeans_alpha, df = test$parameter, lower.tail = FALSE), 3))
          ),
          br(),
          paste0("4. 결론 : ", ifelse(test$p.value < input$twomeans_alpha, "\\(H_0\\) 기각.", "\\(H_0\\) 기각 못함")),
          br(),
          br(),
          tags$h2("해석"),
          br(),
          paste0( input$twomeans_alpha * 100, "% 유의수준에서, ",
                  "평균 차이가 ", test$null.value, " 이라는 귀무가설을 ",
                  ifelse(test$p.value < input$twomeans_alpha, "기각한다", "기각하지 않는다"),
                  " \\((p\\)-값 ", ifelse(test$p.value < 0.001, "< 0.001", paste0("\\(=\\) ", round(test$p.value, 3))), ")", ".")
        )
      } else if (  input$twomeans_popsd == TRUE) {
        test <- t.test3(x = dat1, y = dat2, V1 = input$twomeans_sigma21, V2 = input$twomeans_sigma22, m0 = input$twomeans_h0, alpha = input$twomeans_alpha, alternative = input$twomeans_alternative)
        withMathJax(
          tags$h2("데이터"),
          br(),
          paste(c("\\(표본_1=\\)", paste(dat1, collapse = ", ")), collapse = " "),
          br(),
          paste(c("\\(표본_2=\\)", paste(dat2, collapse = ", ")), collapse = " "),
          br(),
          paste0("\\(n_1 =\\) ", length(dat1)),
          br(),
          paste0("\\(n_2 =\\) ", length(dat2)),
          br(),
          paste0("\\(\\bar{x}_1 =\\) ", round(mean(dat1), 3)),
          br(),
          paste0("\\(\\bar{x}_2 =\\) ", round(mean(dat2), 3)),
          br(),
          paste0("\\(\\sigma^2_1 =\\) ", round(input$twomeans_sigma21, 3)),
          br(),
          paste0("\\(\\sigma^2_2 =\\) ", round(input$twomeans_sigma22, 3)),
          br(),
          br(),
          tags$h2("신뢰구간 - 양측"),
          br(),
          paste0(
            (1 - input$twomeans_alpha) * 100, "% Confidence Interval for \\(\\mu_1 - \\mu_2 = \\bar{x}_1 - \\bar{x}_2 \\pm z_{\\alpha/2} \\sqrt{\\dfrac{\\sigma^2_1}{n_1} + \\dfrac{\\sigma^2_2}{n_2}} = \\) ",
            round(test$mean1, 3), ifelse(test$mean2 >= 0, paste0(" - ", round(test$mean2, 3)), paste0(" + ", round(abs(test$mean2), 3))), "  \\( \\pm \\)", " \\( ( \\)", round(qnorm(input$twomeans_alpha / 2, lower.tail = FALSE), 3), " * ", round(test$S, 3), "\\( ) \\) ", "\\( = \\) ",
            "[", round(test$LCL, 3), "; ", round(test$UCL, 3), "]"
          ),
          br(),
          br(),
          tags$h2("가설 검정"),
          br(),
          paste0("1. \\(H_0 : \\mu_1 - \\mu_2 = \\) ", input$twomeans_h0, " and \\(H_1 : \\mu_1 - \\mu_2 \\) ", ifelse(input$twomeans_alternative == "two.sided", "\\( \\neq \\) ", ifelse(input$twomeans_alternative == "greater", "\\( > \\) ", "\\( < \\) ")), input$twomeans_h0),
          br(),
          paste0(
            "2. 검정 통계량 : \\(z_{obs} = \\dfrac{(\\bar{x}_1 - \\bar{x}_2) - (\\mu_1 - \\mu_2)}{\\sqrt{\\dfrac{\\sigma^2_1}{n_1} + \\dfrac{\\sigma^2_2}{n_2}}} = \\) ",
            "(", round(test$mean1, 3), ifelse(test$mean2 >= 0, paste0(" - ", round(test$mean2, 3)), paste0(" + ", round(abs(test$mean2), 3))), ifelse(input$twomeans_h0 >= 0, paste0(" - ", input$twomeans_h0), paste0(" + ", abs(input$twomeans_h0))), ") / ", round(test$S, 3), " \\( = \\) ",
            round(test$statistic, 3)
          ),
          br(),
          paste0(
            "3. 임계값 :", ifelse(input$twomeans_alternative == "two.sided", " \\( \\pm z_{\\alpha/2} = \\pm z(\\)", ifelse(input$twomeans_alternative == "greater", " \\( z_{\\alpha} = z(\\)", " \\( -z_{\\alpha} = -z(\\)")),
            ifelse(input$twomeans_alternative == "two.sided", input$twomeans_alpha / 2, input$twomeans_alpha), "\\()\\)", " \\( = \\) ",
            ifelse(input$twomeans_alternative == "two.sided", "\\( \\pm \\)", ifelse(input$twomeans_alternative == "greater", "", " -")),
            ifelse(input$twomeans_alternative == "two.sided", round(qnorm(input$twomeans_alpha / 2, lower.tail = FALSE), 3), round(qnorm(input$twomeans_alpha, lower.tail = FALSE), 3))
          ),
          br(),
          paste0("4. 결론 : ", ifelse(test$p.value < input$twomeans_alpha, "\\(H_0\\) 기각.", "\\(H_0\\) 기각 못함")),
          br(),
          br(),
          tags$h2("해석"),
          br(),
          paste0( input$twomeans_alpha * 100, "% 유의수준에서, ",
                  "평균 차이가 ", test$null.value, " 이라는 귀무가설을 ",
                  ifelse(test$p.value < input$twomeans_alpha, "기각한다", "기각하지 않는다"),
                  " \\((p\\)-값 ", ifelse(test$p.value < 0.001, "< 0.001", paste0("\\(=\\) ", round(test$p.value, 3))), ")", ".")
        )
      }
    })

    output$plot_twomean <- renderPlot({
      if ( input$twomeans_popsd == FALSE & input$twomeans_var.equal == TRUE) {
        dat1 <- as.numeric(unlist(strsplit(input$twomeans_sample1, ",")))
        dat2 <- as.numeric(unlist(strsplit(input$twomeans_sample2, ",")))
        test <- t.test(x = dat1, y = dat2, mu = input$twomeans_h0, alternative = input$twomeans_alternative, conf.level = 1 - input$twomeans_alpha, paired = FALSE, var.equal = TRUE)
        if (input$twomeans_alternative == "two.sided") {
          funcShaded <- function(x) {
            y <- dt(x, df = test$parameter)
            y[x < qt(input$twomeans_alpha / 2, df = test$parameter, lower.tail = FALSE) & x > qt(input$twomeans_alpha / 2, df = test$parameter, lower.tail = TRUE) ] <- NA
            return(y)
          }
        } else if (input$twomeans_alternative == "greater") {
          funcShaded <- function(x) {
            y <- dt(x, df = test$parameter)
            y[x < qt(input$twomeans_alpha, df = test$parameter, lower.tail = FALSE) ] <- NA
            return(y)
          }
        } else if (input$twomeans_alternative == "less") {
          funcShaded <- function(x) {
            y <- dt(x, df = test$parameter)
            y[x > qt(input$twomeans_alpha, df = test$parameter, lower.tail = TRUE) ] <- NA
            return(y)
          }
        }

        p <- ggplot(data.frame(x = c(qt(0.999, df = test$parameter, lower.tail = FALSE), qt(0.999, df = test$parameter, lower.tail = TRUE))), aes(x = x)) +

          stat_function( fun = dt, fill="gray90", args = list(df = test$parameter)) +
          stat_function( fun = funcShaded, geom = "area", fill = "sky blue", alpha = 0.8) +

          theme_minimal() +
          geom_vline(xintercept = test$statistic, color = "steelblue") +
          geom_text(aes(x = test$statistic, label = paste0("검정 통계량 = ", round(test$statistic, 3)), y = 0.2), colour = "steelblue", angle = 90, vjust = 1.3, text = element_text(size = 11)) +
          ggtitle(paste0("t-분포", " t(", round(test$parameter, 3), ")")) +
          theme(plot.title = element_text(face = "bold", hjust = 0.5)) +
          ylab("밀도") +
          xlab("x")
        p

      } else if ( input$twomeans_popsd == FALSE & input$twomeans_var.equal == FALSE) {
        dat1 <- as.numeric(unlist(strsplit(input$twomeans_sample1, ",")))
        dat2 <- as.numeric(unlist(strsplit(input$twomeans_sample2, ",")))
        test <- t.test(x = dat1, y = dat2, mu = input$twomeans_h0, alternative = input$twomeans_alternative, conf.level = 1 - input$twomeans_alpha, paired = FALSE, var.equal = FALSE)
        if (input$twomeans_alternative == "two.sided") {
          funcShaded <- function(x) {
            y <- dt(x, df = test$parameter)
            y[x < qt(input$twomeans_alpha / 2, df = test$parameter, lower.tail = FALSE) | x > qt(input$twomeans_alpha / 2, df = test$parameter, lower.tail = TRUE) ] <- NA
            return(y)
          }
        } else if (input$twomeans_alternative == "greater") {
          funcShaded <- function(x) {
            y <- dt(x, df = test$parameter)
            y[x < qt(input$twomeans_alpha, df = test$parameter, lower.tail = FALSE) ] <- NA
            return(y)
          }
        } else if (input$twomeans_alternative == "less") {
          funcShaded <- function(x) {
            y <- dt(x, df = test$parameter)
            y[x > qt(input$twomeans_alpha, df = test$parameter, lower.tail = TRUE) ] <- NA
            return(y)
          }
        }
        p <- ggplot(data.frame(x = c(qt(0.999, df = test$parameter, lower.tail = FALSE), qt(0.999, df = test$parameter, lower.tail = TRUE))), aes(x = x)) +
          stat_function( fun = dt, fill="gray90", args = list(df = test$parameter)) +
          stat_function( fun = funcShaded, geom = "area", fill = "sky blue", alpha = 0.8) +
          theme_minimal() +
          geom_vline(xintercept = test$statistic, color = "steelblue") +
          geom_text(aes(x = test$statistic, label = paste0("검정 통계량Here is the rest of the code with the bug fixed:

= ", round(test$statistic, 3)), y = 0.2), colour = "steelblue", angle = 90, vjust = 1.3, text = element_text(size = 11)) +
          ggtitle(paste0("t-분포", " t(", round(test$parameter, 3), ")")) +
          theme(plot.title = element_text(face = "bold", hjust = 0.5)) +
          ylab("밀도") +
          xlab("x")
        p

      } else if ( input$twomeans_popsd == TRUE ) {
        dat1 <- as.numeric(unlist(strsplit(input$twomeans_sample1, ",")))
        dat2 <- as.numeric(unlist(strsplit(input$twomeans_sample2, ",")))
        test <- t.test3(x = dat1, y = dat2,
                        V1 = input$twomeans_sigma21, V2 = input$twomeans_sigma22,
                        m0 = input$twomeans_h0, alpha = input$twomeans_alpha, alternative = input$twomeans_alternative)
        if (input$twomeans_alternative == "two.sided") {
          funcShaded <- function(x) {
            y <- dnorm(x, mean = 0, sd = 1)
            y[x < qnorm(input$twomeans_alpha / 2, mean = 0, sd = 1, lower.tail = FALSE) | x > qnorm(input$twomeans_alpha / 2, mean = 0, sd = 1, lower.tail = TRUE) ] <- NA
            return(y)
          }
        } else if (input$twomeans_alternative == "greater") {
          funcShaded <- function(x) {
            y <- dnorm(x, mean = 0, sd = 1)
            y[x < qnorm(input$twomeans_alpha, mean = 0, sd = 1, lower.tail = FALSE) ] <- NA
            return(y)
          }
        } else if (input$twomeans_alternative == "less") {
          funcShaded <- function(x) {
            y <- dnorm(x, mean = 0, sd = 1)
            y[x > qnorm(input$twomeans_alpha, mean = 0, sd = 1, lower.tail = TRUE) ] <- NA
            return(y)
          }
        }
        p <- ggplot(data.frame(x = c(qnorm(0.999, mean = 0, sd = 1, lower.tail = FALSE), qnorm(0.999, mean = 0, sd = 1, lower.tail = TRUE))), aes(x = x)) +
          stat_function( fun = dnorm, fill="gray90", args = list(mean = 0, sd = 1)) +
          stat_function( fun = funcShaded, geom = "area", fill = "sky blue", alpha = 0.8) +
          theme_minimal() +
          geom_vline(xintercept = test$statistic, color = "steelblue") +
          geom_text(aes(x = test$statistic, label = paste0("검정 통계량 = ", round(test$statistic, 3)), y = 0.2), colour = "steelblue", angle = 90, vjust = 1.3, text = element_text(size = 11)) +
          ggtitle(paste0("정규 분포 N(0,1)")) +
          theme(plot.title = element_text(face = "bold", hjust = 0.5)) +
          ylab("밀도") +
          xlab("x")
        p
      }
    })

    output$table_twomean <- render_gt({
      dat1 <- as.numeric(unlist(strsplit(input$twomeans_sample1, ",")))
      dat2 <- as.numeric(unlist(strsplit(input$twomeans_sample2, ",")))

      tibble(변수1 = dat1, 변수2 = dat2) %>%
        gt()
    })

  })
}


ui <- fluidPage(
  titlePanel("2표본 평균 가설 검정"),
  two_means_UI("twomeans")
)

server <- function(input, output, session) {
  two_means_server("twomeans")
}

shinyApp(ui, server)

2 코딩

라이센스

CC BY-SA-NC & GPL-3