One-Sample Wilcoxon Signed-Rank Test Calculator | Single Sample Analysis

Compare Sample Median to Hypothesized Value Without Normality Assumptions

Free online one-sample Wilcoxon signed-rank test calculator. Compare your sample median to a hypothesized value without requiring normality. Upload data or enter values for instant statistical analysis.

Tools
Author
Affiliation
Published

April 7, 2025

Modified

April 16, 2025

Keywords

one sample wilcoxon test, single sample wilcoxon calculator, wilcoxon signed rank test calculator, non parametric one sample test, test sample median, one sample nonparametric test, signed rank test online

Key Takeaways: One-Sample Wilcoxon Signed-Rank Test

Tip
  • Purpose: Non-parametric alternative to the one-sample t-test for comparing a sample median to a hypothesized value
  • When to use: When data doesn’t meet normality assumptions or contains outliers
  • Data requirements: At least 5 observations recommended; works with ordinal data
  • Null hypothesis: The sample median equals the hypothesized value
  • Interpretation: If p < 0.05, there is a significant difference between the sample median and the hypothesized value
  • Advantages: More robust with non-normal data; resistant to outliers; tests the median (more appropriate for skewed distributions)

What is the One-Sample Wilcoxon Signed-Rank Test?

The one-sample Wilcoxon signed-rank test is a non-parametric statistical method used to determine whether a sample median differs from a hypothesized value. It serves as a robust alternative to the one-sample t-test when your data doesn’t follow a normal distribution or when working with ordinal data.

Tip

When to use the one-sample Wilcoxon signed-rank test:

  • When testing if a sample’s median differs from a specified value
  • When your data doesn’t follow a normal distribution
  • When working with ordinal data or ranked measurements
  • When your sample contains outliers that would skew a t-test
  • When you have a small sample size and cannot verify normality

This online calculator allows you to quickly perform a one-sample Wilcoxon signed-rank test, visualize your data, and interpret the results with confidence.



#| '!! shinylive warning !!': |
#|   shinylive does not work in self-contained HTML documents.
#|   Please set `embed-resources: false` in your metadata.
#| standalone: true
#| viewerHeight: 1400
library(shiny)
library(bslib)
library(ggplot2)
library(bsicons)
library(vroom)
library(shinyjs)

ui <- page_sidebar(
  title = "One-Sample Wilcoxon Test",
  useShinyjs(),  # Enable shinyjs for resetting inputs
  sidebar = sidebar(
    width = 400,

    card(
      card_header("Data Input"),
      accordion(
        accordion_panel(
          "Manual Input",
          textAreaInput("sample_input", "Sample Data [One value per row]", rows = 8,
                     placeholder = "Paste values here..."),
          div(
            actionLink("use_example", "Use example data", style = "color:#0275d8;"),
            tags$span(bs_icon("file-earmark-text"), style = "margin-left: 5px; color: #0275d8;")
          )
        ),
        accordion_panel(
          "File Upload",
          fileInput("file_upload", "Upload CSV or TXT file:",
                   accept = c("text/csv", "text/plain", ".csv", ".txt")),
          checkboxInput("header", "File has header", TRUE),
          conditionalPanel(
            condition = "output.file_uploaded",
            div(
              selectInput("sample_var", "Sample variable:", choices = NULL),
              actionButton("clear_file", "Clear File", class = "btn-danger btn-sm")
            )
          )
        ),
        id = "input_method",
        open = 1
      ),
      
      # Advanced Options accordion
      accordion(
        accordion_panel(
          "Advanced Options",
          
          card(
            card_header("Null Hypothesis:"),
            card_body(
              tags$div(style = "margin-bottom: 10px;",
                numericInput("null_hypothesis", "mu =", 0.0, width = "100%")
              )
            )
          ),
          
          card(
            card_header("Alternative Hypothesis:"),
            card_body(
              radioButtons("alternative", NULL,
                         choices = c("Two-sided" = "two.sided", 
                                    "mu < specified value" = "less",
                                    "mu > specified value" = "greater"),
                         selected = "two.sided")
            )
          ),
          
          card(
            card_header("Type of Test:"),
            card_body(
              radioButtons("method", NULL,
                         choices = c("Default" = "default", 
                                    "Exact" = "exact",
                                    "Normal approximation" = "normal",
                                    "Normal approximation with continuity correction" = "correct"),
                         selected = "default")
            )
          )
        ),
        open = FALSE
      ),
      
      actionButton("run_test", "Run Test", class = "btn btn-primary")
    ),

    hr(),

    card(
      card_header("Interpretation"),
      card_body(
        div(class = "alert alert-info",
          tags$ul(
            tags$li("The one-sample Wilcoxon test compares the median of a sample to a hypothesized value."),
            tags$li(tags$b("Null hypothesis:"), " The sample median equals the specified value."),
            tags$li(tags$b("Alternative:"), " The sample median differs from (or is less/greater than) the specified value."),
            tags$li("If p-value < 0.05, there is a significant difference between the sample median and the hypothesized value.")
          )
        )
      )
    )
  ),

  layout_column_wrap(
    width = 1,

    card(
      card_header("Test Results"),
      card_body(
        navset_tab(
          nav_panel("Results", uiOutput("error_message"), verbatimTextOutput("test_results")),
          nav_panel("Explanation", div(style = "font-size: 0.9rem;",
            p("The Wilcoxon Signed-Rank Test is a non-parametric alternative to the one-sample t-test:"),
            tags$ul(
              tags$li("It does not assume normality, making it more robust than the t-test."),
              tags$li("The test ranks the absolute differences between each observation and the hypothesized median."),
              tags$li("Signs of the original differences are assigned to the ranks, and the test statistic is calculated."),
              tags$li("A small p-value indicates the sample median likely differs from the hypothesized value.")
            )
          ))
        )
      )
    ),

    card(
      card_header("Visual Assessment"),
      card_body(
        navset_tab(
          nav_panel("Histogram",
            navset_tab(
              nav_panel("Plot", plotOutput("histogram")),
              nav_panel("Explanation", div(style = "font-size: 0.9rem;",
                p("The histogram shows the distribution of your sample:"),
                tags$ul(
                  tags$li("The vertical dashed line shows the sample median."),
                  tags$li("The vertical dotted line shows the hypothesized median value."),
                  tags$li("Comparing these lines helps you visualize the difference being tested.")
                )
              ))
            )
          ),
          nav_panel("Boxplot",
            navset_tab(
              nav_panel("Plot", plotOutput("boxplot")),
              nav_panel("Explanation", div(style = "font-size: 0.9rem;",
                p("The boxplot shows the distribution of your sample:"),
                tags$ul(
                  tags$li("The box represents the interquartile range (IQR), with the median shown as a horizontal line."),
                  tags$li("Whiskers extend to the smallest and largest values within 1.5 times the IQR."),
                  tags$li("The horizontal dotted line shows the hypothesized median value."),
                  tags$li("Points outside the whiskers are potential outliers.")
                )
              ))
            )
          ),
          nav_panel("Differences",
            navset_tab(
              nav_panel("Plot", plotOutput("differences")),
              nav_panel("Explanation", div(style = "font-size: 0.9rem;",
                p("The difference plot shows:"),
                tags$ul(
                  tags$li("Each observation's difference from the hypothesized value."),
                  tags$li("Positive values are above the hypothesized median, negative values are below."),
                  tags$li("The horizontal dotted line at 0 represents no difference from the hypothesized value."),
                  tags$li("This plot helps visualize the direction and magnitude of differences.")
                )
              ))
            )
          )
        )
      )
    )
  )
)

server <- function(input, output, session) {
  # Example data
  example_data <- "8.5\n7.2\n12.4\n10.8\n9.3\n6.7\n11.5\n8.9\n10.2\n7.8"

  # Track input method
  input_method <- reactiveVal("manual")
  
  # Function to clear file inputs
  clear_file_inputs <- function() {
    updateSelectInput(session, "sample_var", choices = NULL)
    reset("file_upload")
  }
  
  # Function to clear text inputs
  clear_text_inputs <- function() {
    updateTextAreaInput(session, "sample_input", value = "")
  }

  # When example data is used, clear file inputs and set text inputs
  observeEvent(input$use_example, {
    input_method("manual")
    clear_file_inputs()
    updateTextAreaInput(session, "sample_input", value = example_data)
  })

  # When file is uploaded, clear text inputs and set file method
  observeEvent(input$file_upload, {
    if (!is.null(input$file_upload)) {
      input_method("file")
      clear_text_inputs()
    }
  })

  # When clear file button is clicked, clear file and set manual method
  observeEvent(input$clear_file, {
    input_method("manual")
    clear_file_inputs()
  })
  
  # When text input changes, clear file inputs if it has content
  observeEvent(input$sample_input, {
    if (!is.null(input$sample_input) && nchar(input$sample_input) > 0) {
      input_method("manual")
      clear_file_inputs()
    }
  }, ignoreInit = TRUE)

  file_data <- reactive({
    req(input$file_upload)
    tryCatch({
      vroom::vroom(input$file_upload$datapath, delim = NULL, col_names = input$header, show_col_types = FALSE)
    }, error = function(e) {
      showNotification(paste("File read error:", e$message), type = "error")
      NULL
    })
  })

  observe({
    df <- file_data()
    if (!is.null(df)) {
      num_vars <- names(df)[sapply(df, is.numeric)]
      updateSelectInput(session, "sample_var", choices = num_vars)
    }
  })

  output$file_uploaded <- reactive({
    !is.null(input$file_upload)
  })
  outputOptions(output, "file_uploaded", suspendWhenHidden = FALSE)

  # Function to parse text input
  parse_text_input <- function(text) {
    if (is.null(text) || text == "") return(NULL)
    input_lines <- strsplit(text, "\\r?\\n")[[1]]
    input_lines <- input_lines[input_lines != ""]
    numeric_values <- suppressWarnings(as.numeric(input_lines))
    if (all(is.na(numeric_values))) return(NULL)
    return(na.omit(numeric_values))
  }

  # Get sample values
  sample_values <- reactive({
    if (input_method() == "file" && !is.null(file_data()) && !is.null(input$sample_var)) {
      df <- file_data()
      return(na.omit(df[[input$sample_var]]))
    } else {
      return(parse_text_input(input$sample_input))
    }
  })
  
  # Get mu value
  mu_value <- reactive({
    return(input$null_hypothesis)
  })

  # Validate input data
  validate_data <- reactive({
    sample <- sample_values()
    
    if (is.null(sample)) {
      return("Error: Please check your input. Make sure all values are numeric.")
    }
    
    if (length(sample) < 5) {
      return("Error: At least 5 observations are recommended for the Wilcoxon test.")
    }
    
    # Check if all values are equal to mu (test isn't appropriate)
    if (all(sample == mu_value())) {
      return("Error: All values equal the null hypothesis value. The Wilcoxon test is not applicable.")
    }
    
    # Check if values after subtracting mu contain zeros (warn about ties)
    zeroes <- sum(sample == mu_value())
    if (zeroes > 0) {
      return(paste0("Warning: ", zeroes, " value(s) equal the null hypothesis value and will be excluded from the test."))
    }
    
    return(NULL)
  })

   output$error_message <- renderUI({
    error <- validate_data()
    if (!is.null(error) && input$run_test > 0) {
      if (startsWith(error, "Warning")) {
        div(class = "alert alert-warning", error)
      } else {
        div(class = "alert alert-danger", error)
      }
    }
  })

  # Run the Wilcoxon test
  test_result <- eventReactive(input$run_test, {
    error <- validate_data()
    if (!is.null(error) && startsWith(error, "Error")) return(NULL)
    
    # Fix the issue with exact and correct parameters
    # Get the method selected by the user
    method_choice <- input$method
    
    # Set parameters based on method
    if (method_choice == "default") {
      # For default method, let R decide based on sample size
      wilcox.test(
        sample_values(), 
        mu = mu_value(),
        alternative = input$alternative
      )
    } else if (method_choice == "exact") {
      # For exact method
      wilcox.test(
        sample_values(), 
        mu = mu_value(),
        alternative = input$alternative,
        exact = TRUE,
        correct = FALSE
      )
    } else if (method_choice == "normal") {
      # For normal approximation without correction
      wilcox.test(
        sample_values(), 
        mu = mu_value(),
        alternative = input$alternative,
        exact = FALSE,
        correct = FALSE
      )
    } else if (method_choice == "correct") {
      # For normal approximation with correction
      wilcox.test(
        sample_values(), 
        mu = mu_value(),
        alternative = input$alternative,
        exact = FALSE,
        correct = TRUE
      )
    }
  })

  # Display test results
  output$test_results <- renderPrint({
    if (is.null(test_result())) return(NULL)
    
    result <- test_result()
    sample <- sample_values()
    
    # Use alternative input for interpretation
    alt_text <- switch(
      input$alternative,
      "two.sided" = "different from",
      "less" = "less than",
      "greater" = "greater than"
    )
    
    cat("One-Sample Wilcoxon Signed Rank Test Results:\n")
    cat("============================================\n\n")
    cat("V statistic:", result$statistic, "\n")
    
    # For normal approximation, show Z score
    if (input$method %in% c("normal", "correct") || (input$method == "default" && length(sample) >= 50)) {
      # Calculate Z score manually (approximate)
      n_effective <- sum(sample != mu_value())
      V <- as.numeric(result$statistic)
      
      # Expected value and standard deviation under H0
      expected_V <- n_effective * (n_effective + 1) / 4
      sd_V <- sqrt(n_effective * (n_effective + 1) * (2 * n_effective + 1) / 24)
      
      # Z score calculation
      correction <- if(input$method == "correct" || (input$method == "default" && length(sample) >= 50)) 0.5 else 0
      Z <- (V - expected_V - correction) / sd_V
      
      cat("Z score (approximation):", round(Z, 4), "\n")
    }
    
    cat("p-value:", round(result$p.value, 6), "\n\n")
    
    cat("Sample Summary:\n")
    cat("---------------\n")
    cat("Sample size:", length(sample), "\n")
    cat("Sample median:", round(median(sample), 4), "\n")
    cat("Sample mean:", round(mean(sample), 4), "\n")
    cat("First quartile (Q1):", round(quantile(sample, 0.25), 4), "\n")
    cat("Third quartile (Q3):", round(quantile(sample, 0.75), 4), "\n\n")
    
    cat("Test Information:\n")
    cat("-----------------\n")
    cat("Hypothesized median:", mu_value(), "\n")
    cat("Alternative hypothesis: true location is", alt_text, mu_value(), "\n")
    cat("Method:", switch(input$method,
                         "default" = "automatic (exact for small samples, normal approximation for large)",
                         "exact" = "exact",
                         "normal" = "normal approximation",
                         "correct" = "normal approximation with continuity correction"), "\n\n")

    cat("Conclusion:\n")
    cat("-----------\n")
    if (result$p.value < 0.05) {
      cat("There is a significant difference (p < 0.05).\n")
      cat("The sample median is significantly", alt_text, "the hypothesized value of", mu_value(), ".\n")
    } else {
      cat("Interpretation: No significant difference detected (p ≥ 0.05).\n")
      cat("We cannot conclude that the sample median is", alt_text, "the hypothesized value of", mu_value(), ".\n")
    }
  })

  # Generate histogram
  output$histogram <- renderPlot({
    req(input$run_test > 0, !is.null(sample_values()))
    
    sample <- sample_values()
    
    ggplot(data.frame(value = sample), aes(x = value)) +
      geom_histogram(bins = min(30, max(10, length(sample)/3)), 
                    fill = "#5dade2", color = "#2874a6", alpha = 0.7) +
      geom_vline(xintercept = median(sample), linetype = "dashed", 
                color = "#c0392b", size = 1.5) +
      geom_vline(xintercept = mu_value(), linetype = "dotted", 
                color = "#8e44ad", size = 1.5) +
      annotate("text", x = median(sample), y = 0, 
               label = paste("Median =", round(median(sample), 2)), 
               vjust = -1, hjust = ifelse(median(sample) > mu_value(), 1.1, -0.1),
               color = "#c0392b", fontface = "bold") +
      annotate("text", x = mu_value(), y = 0, 
               label = paste("H₀ =", mu_value()), 
               vjust = -3, hjust = ifelse(mu_value() > median(sample), 1.1, -0.1),
               color = "#8e44ad", fontface = "bold") +
      labs(title = "Distribution of Sample Values",
           subtitle = "With sample median and hypothesized value",
           x = "Value",
           y = "Frequency") +
      theme_minimal(base_size = 14)
  })
  
  # Generate boxplot
  output$boxplot <- renderPlot({
    req(input$run_test > 0, !is.null(sample_values()))
    
    sample <- sample_values()
    
    # Create data frame for boxplot
    df <- data.frame(value = sample)
    
    # Calculate summary statistics for annotation
    sample_median <- median(sample)
    
    ggplot(df, aes(y = value, x = factor(1))) +
      geom_boxplot(fill = "#5dade2", width = 0.5, alpha = 0.7, outlier.color = "#e74c3c") +
      geom_jitter(width = 0.1, alpha = 0.5, color = "#34495e") +
      geom_hline(yintercept = mu_value(), linetype = "dotted", 
                color = "#8e44ad", size = 1.5) +
      annotate("text", y = mu_value(), x = 1.5, 
               label = paste("H₀ =", mu_value()), 
               hjust = 0, vjust = ifelse(mu_value() > sample_median, -0.5, 1.5),
               color = "#8e44ad", fontface = "bold") +
      labs(title = "Boxplot of Sample Values",
           subtitle = "With hypothesized value",
           y = "Value") +
      theme_minimal(base_size = 14) +
      theme(axis.title.x = element_blank(),
            axis.text.x = element_blank(),
            axis.ticks.x = element_blank())
  })
  
  # Generate differences plot
  output$differences <- renderPlot({
    req(input$run_test > 0, !is.null(sample_values()))
    
    sample <- sample_values()
    mu <- mu_value()
    
    # Calculate differences from hypothesized value
    diffs <- sample - mu
    
    # Create data frame for difference plot
    df <- data.frame(
      index = 1:length(diffs),
      difference = diffs
    )
    
    # Determine color based on difference
    df$color <- ifelse(df$difference > 0, "Positive", "Negative")
    
    ggplot(df, aes(x = index, y = difference, fill = color)) +
      geom_col(width = 0.7, alpha = 0.8) +
      geom_hline(yintercept = 0, linetype = "dotted", 
                color = "black", size = 1) +
      scale_fill_manual(values = c("Positive" = "#2ecc71", "Negative" = "#e74c3c")) +
      labs(title = "Differences from Hypothesized Value",
           subtitle = paste("Value - H₀ (", mu, ")", sep = ""),
           x = "Observation Index",
           y = "Difference") +
      theme_minimal(base_size = 14) +
      theme(legend.title = element_blank(),
            legend.position = "top")
  })
}

shinyApp(ui = ui, server = server)

One-Sample Wilcoxon Test vs. One-Sample t-Test

When should you choose the Wilcoxon signed-rank test over the traditional t-test?

Feature Wilcoxon Signed-Rank Test One-Sample t-Test
Distribution assumptions No normality assumption Assumes normal distribution
Central tendency measured Tests median Tests mean
Resistance to outliers Highly resistant Sensitive to outliers
Efficiency Slightly less powerful when data is normal More powerful with normal data
Data types Works with ordinal data Requires interval/ratio data
Small samples Appropriate for small non-normal samples Less reliable with small non-normal samples

The one-sample Wilcoxon signed-rank test is generally recommended when:

  1. Your data shows clear deviation from normality (asymmetry, outliers, etc.)
  2. You’re working with small samples where normality is uncertain
  3. Your research question specifically concerns the median rather than the mean
  4. You’re analyzing ranked or ordinal data

How the One-Sample Wilcoxon Signed-Rank Test Works

The one-sample Wilcoxon signed-rank test works by analyzing the ranks of the absolute differences between each observation and the hypothesized value:

Mathematical Procedure

  1. Calculate differences: For each observation, calculate the difference between the observed value and the hypothesized value (\(d_i = x_i - \mu_0\))
  2. Exclude zeros: Remove any observations where the difference is exactly zero
  3. Rank absolute differences: Rank the absolute values of the differences from smallest to largest
  4. Assign signs: Attach the original sign of each difference to its rank
  5. Calculate rank sums: Calculate the sum of positive ranks (\(V^+\)) and the sum of negative ranks (\(V^-\))
  6. Determine test statistic: The test statistic \(V\) is typically the sum of positive ranks
  7. Calculate p-value:
    • For small samples (\(n < 10\)): Use exact probability distribution
    • For larger samples: Use normal approximation with
      • Mean = \(n(n+1)/4\)
      • Standard Deviation = \(\sqrt{n(n+1)(2n+1)/24}\)

Assumptions of the One-Sample Wilcoxon Signed-Rank Test

The test has fewer assumptions than parametric tests:

  1. Random sample: The data should be a random sample from the population
  2. Independence: The observations should be independent of each other
  3. Continuous variable: The variable should be continuous (or at least ordinal)
  4. Symmetry: The distribution of differences should be approximately symmetric around the median (not required for large samples)

Statistical Power Considerations

Important

Statistical Power Note: The one-sample Wilcoxon signed-rank test has approximately 95% of the power of the t-test when the t-test’s assumptions are perfectly met. However, when those assumptions are violated (non-normality, outliers), the Wilcoxon test often has substantially greater power.

For optimal statistical power:

  • Use at least 10-15 observations when possible
  • Consider the exact test for small samples
  • With highly skewed data, the Wilcoxon test is almost always more powerful than the t-test

Example 1: Product Weight Quality Control

A manufacturer needs to verify if their product meets the specified weight of 100 grams. They randomly select 12 products from the production line and weigh them.

Data (weights in grams): 96.5, 102.8, 97.3, 101.5, 99.8, 103.2, 98.7, 104.1, 97.9, 100.2, 103.8, 99.5

Analysis Steps:

  1. State hypotheses:

    • \(H_0\): The median product weight equals 100 grams
    • \(H_1\): The median product weight differs from 100 grams
  2. Calculate differences from hypothesized value (100): -3.5, 2.8, -2.7, 1.5, -0.2, 3.2, -1.3, 4.1, -2.1, 0.2, 3.8, -0.5

  3. Rank absolute differences:

    Value Difference Absolute Difference Rank Signed Rank
    96.5 -3.5 3.5 10 -10
    102.8 2.8 2.8 8 8
    97.3 -2.7 2.7 7 -7
    101.5 1.5 1.5 5 5
    99.8 -0.2 0.2 1 -1
    103.2 3.2 3.2 9 9
    98.7 -1.3 1.3 4 -4
    104.1 4.1 4.1 12 12
    97.9 -2.1 2.1 6 -6
    100.2 0.2 0.2 1 1
    103.8 3.8 3.8 11 11
    99.5 -0.5 0.5 3 -3
  4. Calculate sum of signed ranks:

    • Sum of positive ranks: \(V^+ = 8 + 5 + 9 + 12 + 1 + 11 = 46\)
    • Sum of negative ranks: \(V^- = -10 + (-7) + (-1) + (-4) + (-6) + (-3) = -31\)
    • Test statistic \(V = 46\) (sum of positive ranks)
  5. Calculate p-value:

    • For \(n = 12\), using the normal approximation
    • Expected \(V\) under \(H_0 = 12(12+1)/4 = 39\)
    • Standard deviation = \(\sqrt{\frac{12(12+1)(2 \times 12+1)}{24}} = 13.23\)
    • \(Z = \frac{46 - 39}{13.23} = 0.53\)
    • Two-tailed p-value = 0.596

Results:

  • \(V = 46\), \(p = 0.596\)
  • Sample median = 99.65
  • Interpretation: There is no significant evidence that the median product weight differs from the specified 100 grams (\(p > 0.05\)).

How to Report: “A one-sample Wilcoxon signed-rank test indicated that the median product weight (\(\text{Mdn} = 99.65\) g) did not significantly differ from the specified 100 g (\(V = 46\), \(p = 0.596\)), suggesting the production process is meeting the weight specifications.”

Example 2: Patient Recovery Time

A hospital wants to determine if a new treatment protocol has reduced patient recovery time below the historical median of 14 days.

Data (recovery time in days): 10, 12, 9, 15, 8, 11, 7, 13, 10, 9, 12, 8, 11, 10, 9

Results:

  • \(V = 18\), \(p = 0.006\)
  • Sample median = 10
  • Interpretation: There is significant evidence that the median recovery time is less than the historical value of 14 days (\(p < 0.05\)).

How to Report: “A one-sample Wilcoxon signed-rank test showed that the median recovery time under the new protocol (\(\text{Mdn} = 10\) days) was significantly less than the historical median of 14 days (\(V = 18\), \(p = 0.006\)), indicating the new treatment protocol effectively reduces patient recovery time.”

How to Report One-Sample Wilcoxon Test Results

When reporting the results of a one-sample Wilcoxon signed-rank test in academic papers or research reports, include the following elements:

"The sample median ($\text{Mdn} = [value]$) was significantly [higher/lower/different from] 
the hypothesized value of $\mu_0$ ($V = [test statistic]$, $p = [p-value]$)."

For example:

"The sample median ($\text{Mdn} = 25.5$) was significantly higher than 
the hypothesized value of 20 ($V = 45$, $n = 15$, $p = 0.008$)."

Additional information to consider including: - Sample size after excluding ties (\(n\)) - Effect size (\(r = Z/\sqrt{N}\) where \(Z\) is the standardized test statistic) - Confidence interval for the median (if available) - Whether the test was one-tailed or two-tailed - Whether exact or approximate methods were used

APA Style Reporting

For APA style papers (7th edition), report the one-sample Wilcoxon signed-rank test results as follows:

We conducted a one-sample Wilcoxon signed-rank test to examine whether the median [variable] 
differed from [hypothesized value]. Results indicated that the median [variable] ($\text{Mdn} = [value]$) 
was significantly [higher/lower than/different from] the hypothesized value of $\mu_0$ 
($V = [test statistic]$, $z = [z-value if available]$, $p = [exact p-value]$, $r = [effect size]$).

Reporting in Tables

When reporting multiple one-sample Wilcoxon test results in a table, include these columns: - Variable tested - Hypothesized value (\(\mu_0\)) - Sample median - \(V\) statistic - \(Z\) statistic (if using normal approximation) - p-value - Effect size - Sample size

Test Your Understanding

  1. When is the one-sample Wilcoxon signed-rank test most appropriate?
      1. When comparing paired measurements from the same subjects
      1. When comparing a sample median to a hypothesized value with non-normal data
      1. When comparing two independent groups
      1. When testing for correlation between variables
  2. What is the main advantage of the one-sample Wilcoxon test over the one-sample t-test?
      1. It always provides higher statistical power
      1. It can be used with categorical data
      1. It doesn’t require the assumption of normality
      1. It can test multiple hypotheses simultaneously
  3. What does the one-sample Wilcoxon signed-rank test primarily compare?
      1. The sample mean to a hypothesized value
      1. The sample median to a hypothesized value
      1. The sample variance to a hypothesized value
      1. The sample distribution shape to a reference distribution
  4. A researcher finds \(V = 32\), \(p = 0.02\) when testing if a sample differs from a hypothesized value. What can they conclude?
      1. There is no significant difference from the hypothesized value
      1. There is a significant difference from the hypothesized value
      1. The test is invalid
      1. More data is needed
  5. What happens to observations that exactly equal the hypothesized value in the Wilcoxon test?
      1. They are assigned a rank of zero
      1. They are excluded from the analysis
      1. They are averaged with other values
      1. They are treated as positive differences

Answers: 1-B, 2-C, 3-B, 4-B, 5-B

Common Questions About the One-Sample Wilcoxon Test

The one-sample Wilcoxon test compares a single sample’s median to a hypothesized value, while the paired Wilcoxon test compares two related measurements from the same subjects. They use the same underlying statistical method (signed-rank test), but in the paired test, the differences are calculated between matched pairs rather than between each observation and a fixed value.

Observations that exactly equal the hypothesized value result in a difference of zero and are excluded from the analysis. The effective sample size becomes the number of non-zero differences. If you have many such values, this could reduce the power of your test.

For small samples (typically \(n < 50\)), an exact method calculates the precise probability distribution of the test statistic. For larger samples, a normal approximation is used, which estimates the p-value based on the assumption that the test statistic approximately follows a normal distribution. The continuity correction improves this approximation.

Include: the \(V\) statistic, sample size, p-value, and sample median. For example: “The sample median (\(\text{Mdn} = 12.5\)) was significantly higher than the hypothesized value of 10 (\(V = 45\), \(n = 20\), \(p = .008\)).” If using normal approximation, you may also report the \(Z\) statistic.

Yes, the test can be used with small samples, though it becomes more powerful with larger sample sizes. For very small samples (\(n < 5\)), the ability to detect significant differences is limited. With very small samples, it’s advisable to use the exact version of the test rather than the normal approximation.

The sign test is an even simpler non-parametric alternative that only considers the direction of differences (positive or negative) but ignores their magnitude. The Wilcoxon test is generally more powerful because it also takes into account the magnitude of the differences. Use the sign test when only the direction of differences is reliable or when the distribution of differences is highly asymmetric.

Examples of When to Use the One-Sample Wilcoxon Signed-Rank Test

  1. Medical research: Testing if patient pain scores differ from a clinically relevant threshold when pain is measured on an ordinal scale
  2. Quality control: Determining if the median lifetime of components differs from the manufacturer’s specified value
  3. Psychology: Testing if median response times differ from a theoretical standard
  4. Environmental science: Checking if a sample of pollution measurements differs from a regulatory threshold
  5. Market research: Analyzing if customer satisfaction ratings differ from a benchmark value
  6. Education: Evaluating if student performance metrics differ from a national standard
  7. Clinical trials: Assessing if a treatment produces a change from a standardized baseline
  8. Finance: Testing if investment returns differ from a market benchmark
  9. Manufacturing: Verifying if product attributes meet design specifications
  10. Sports science: Comparing athlete performance metrics to established performance standards

References

  • Wilcoxon, F. (1945). Individual comparisons by ranking methods. Biometrics Bulletin, 1(6), 80-83.
  • Hollander, M., & Wolfe, D. A. (1999). Nonparametric statistical methods (2nd ed.). Wiley.
  • Siegel, S., & Castellan, N. J. (1988). Nonparametric statistics for the behavioral sciences (2nd ed.). McGraw-Hill.
  • Conover, W. J. (1999). Practical nonparametric statistics (3rd ed.). John Wiley & Sons.
  • Corder, G. W., & Foreman, D. I. (2014). Nonparametric statistics: A step-by-step approach (2nd ed.). Wiley.
  • Mundry, R., & Fischer, J. (1998). Use of statistical programs for nonparametric tests of small samples often leads to incorrect P values: examples from Animal Behaviour. Animal Behaviour, 56(1), 256-259.
Back to top

Reuse

Citation

BibTeX citation:
@online{kassambara2025,
  author = {Kassambara, Alboukadel},
  title = {One-Sample {Wilcoxon} {Signed-Rank} {Test} {Calculator}
    \textbar{} {Single} {Sample} {Analysis}},
  date = {2025-04-07},
  url = {https://www.datanovia.com/apps/statfusion/analysis/inferential/non-parametric/one-sample/wilcoxon-signed-rank-test-single.html},
  langid = {en}
}
For attribution, please cite this work as:
Kassambara, Alboukadel. 2025. “One-Sample Wilcoxon Signed-Rank Test Calculator | Single Sample Analysis.” April 7, 2025. https://www.datanovia.com/apps/statfusion/analysis/inferential/non-parametric/one-sample/wilcoxon-signed-rank-test-single.html.