rggplot2lettersignificance

Why the cld letters are misaligned on my plot?


I'm using emmeans::cld() to generate significance group letters after an ANOVA, and I want to display them above a ggplot2 boxplot. When I set alpha = 0.05, it works fine but when I want to use delta = 2 , the letters are misaligned : even though both my main dataset and the summary table have the same factor levels in the same order, the letters are not correctly aligned with the x-axis categories.

I tried position = position_identity() and ensured that levels() match in both data frames. But the text labels still appear shifted. Here's a full reproducible example — can someone help me understand what I'm missing?boxplot with misaligned letters

 # Load necessary libraries
    library(tidyverse)
    library(emmeans)
    library(multcomp)
    
    # Step 1: Simulated dataset
    set.seed(123)
    
    # Define levels of the treatment variable
    treatment_levels <- c("Control_0",
                          "Carvone_0.001", "Carvone_0.01",
                          "Eucalyptol_0.001", "Eucalyptol_0.01",
                          "Mint_nanah_0.001", "Mint_nanah_0.01",
                          "Mint_piperita_0.001", "Mint_piperita_0.01",
                          "Mint_pouliot_0.001", "Mint_pouliot_0.01",
                          "Menthone_0.001", "Menthone_0.01",
                          "Pulegone_0.001", "Pulegone_0.01")
    
    # Simulate a dataset
    Microbio_2025 <- tibble(
      Treatment = rep(treatment_levels, each = 6),
      Corrected_Surface = rnorm(6 * length(treatment_levels), mean = 20, sd = 5)
    )
    
    Microbio_2025 <- Microbio_2025 %>%
      mutate(Treatment = factor(Treatment, levels = treatment_levels))
    
    # Step 2: Simple ANOVA model
    anova_microbio <- aov(Corrected_Surface ~ Treatment, data = Microbio_2025)
    
    # Step 3: Grouping letters using emmeans
    grouped_means <- emmeans(anova_microbio, specs = ~ Treatment) %>%
      cld(delta = 2, 
          #alpha = 0.05, 
          Letters = letters) %>%
      as.data.frame() %>%
      mutate(Treatment = factor(Treatment, levels = treatment_levels))
    
    # Step 4: Boxplot + significance letters
    ggplot(data = Microbio_2025, aes(x = Treatment, y = Corrected_Surface, fill = Treatment)) +
      
      geom_boxplot(show.legend = FALSE) +
      
      # Add significance group letters (here is where the alignment issue happens)
      geom_text(data = grouped_means,
                aes(x = Treatment, y = 45, label = .equiv.set),
                position = position_identity(),
                size = 5,
                show.legend = FALSE) +
      
      labs(x = "Tested Samples",
           y = "Corrected surface area (cm²)") +
      
      theme_minimal() +
      theme(axis.text.x = element_text(angle = 45, vjust = 0.5),
            text = element_text(size = 15))

Solution

  • The issue is that your labels contain leading and trailing spaces. Hence, to align your labels with boxplots you can get rid of the spaces using e.g. trimws:

    library(ggplot2)
    
    grouped_means$.equiv.set
    #>  [1] " a              " "  b             " "   c            " "    d           "
    #>  [5] "     e          " "      f         " "       g        " "        h       "
    #>  [9] "         i      " "          j     " "           k    " "            l   "
    #> [13] "             m  " "              n " "               o"
    # Step 4: Boxplot + significance letters
    ggplot(data = Microbio_2025, aes(x = Treatment, y = Corrected_Surface, fill = Treatment)) +
      geom_boxplot(show.legend = FALSE) +
      # Add significance group letters (here is where the alignment issue happens)
      geom_text(
        data = grouped_means,
        aes(x = Treatment, y = 45, label = trimws(.equiv.set)),
        size = 5,
        show.legend = FALSE
      ) +
      labs(
        x = "Tested Samples",
        y = "Corrected surface area (cm²)"
      ) +
      theme_minimal() +
      theme(
        axis.text.x = element_text(angle = 45, vjust = 0.5),
        text = element_text(size = 15)
      )