const-ae/ggsignif

Manual annotation don't work when labels are duplicated

kassambara opened this issue ยท 9 comments

Hi,

As described in issue #6, annotation that contain duplicate contents does not work for grouped plots.

Let's start by some reproducible examples.

Demo data and plot:

library(ggplot2)
library(ggsignif)
p <- ggplot(ToothGrowth, aes(supp, len)) +
    geom_boxplot(aes(color = dose))
  s <- stat.test <- data.frame(
    stringsAsFactors=FALSE,
    p.adj = c(0.000176, 3.96e-06, 0.0392, 1.36e-06, 1.4e-07, 9.16e-05),
    signif = c("****", "****", "****", "****", "****", "****"),
    signif2 = c("a", "b", "c", "d", "e", "f"),
    y_position = c(31.827, 33.5295, 35.232, 34.917, 37.1445, 39.372),
    xmin = c(0.7, 0.7, 1, 1.7, 1.7, 2),
    xmax = c(1, 1.3, 1.3, 2, 2.3, 2.3),
    group = rep(1:2, each = 3),
    supp = as.factor(rep(c("OJ", "VC"), each = 3))
  )
s
     p.adj signif signif2 y_position xmin xmax group supp
1 1.76e-04   ****       a    31.8270  0.7  1.0     1   OJ
2 3.96e-06   ****       b    33.5295  0.7  1.3     1   OJ
3 3.92e-02   ****       c    35.2320  1.0  1.3     1   OJ
4 1.36e-06   ****       d    34.9170  1.7  2.0     2   VC
5 1.40e-07   ****       e    37.1445  1.7  2.3     2   VC
6 9.16e-05   ****       f    39.3720  2.0  2.3     2   VC

Th following R code works because all annotation contents are distinct:

p + geom_signif(
    aes(xmin = xmin, xmax = xmax, y_position = y_position, annotations = signif2),
    data = stat.test, manual = TRUE, tip_length = 0
    )

Rplot05

This one does not work because annotation contents are duplicated:

p + geom_signif(
    aes(xmin = xmin, xmax = xmax, y_position = y_position, annotations = signif),
    data = stat.test,
    manual = TRUE, tip_length = 0
    )

Rplot06

A workaround has been provided in discussion: #6

p + geom_signif(
  xmin = s$xmin, xmax = s$xmax, 
  y_position = s$y_position, annotation = s$signif,
  tip_length = 0
)

Rplot07

My problem is that, the above solution does not work when facet is used:

p + geom_signif(
  xmin = s$xmin, xmax = s$xmax, 
  y_position = s$y_position, annotation = s$signif,
  tip_length = 0
) +
  facet_wrap(~supp)

Rplot08

Aesthetic mapping is better for faceting but annotations are not displayed correctly:

p + geom_signif(
    aes(xmin = xmin, xmax = xmax, y_position = y_position, annotations = signif),
    data = stat.test,
    manual = TRUE, tip_length = 0
    )+
  facet_wrap(~supp)

Rplot09

Any suggestions?

Hi Alboukadel,

thank you for the excellent issue description and the reproducible example. Please execuse the delay, I am currently travelling (until the end of the month), and although I do have my laptop with me, I cannot promise that I will find time to look into the underlying problem and implement a fix.

But, i would be very happy to accept a pull request. From your repos, I have the impression that you have the necessary experience with ggplot extensions ;)

Best, Constantin

Hi Constatin,

Thank you again for this awesome package.

I found a quick fix to my issue:

  1. Adding group column: each row (i.e., comparison) is considered as a different group
  2. Specifying the group in aes()
stat.test$group <- 1:nrow(stat.test)
p + geom_signif(
  aes(xmin = xmin, xmax = xmax, y_position = y_position, annotations = signif, group = group),
  data = stat.test, manual = TRUE, tip_length = 0, vjust = 0.5
)

Rplot10

From my point of view, when manual = TRUE, then each annotation can be automatically considered as a different group.

If you think that it's a good user-experience to have this grouping done automatically, then the function geom_signif() can be simply modified as follow:

Replacing :

group=if(manual){rep(data$group, times=3)} (in line:

annotation=rep(annotations, times=3), group=if(manual){rep(data$group, times=3)}else{rep(seq_along(xmin), times=3)})
)

by:

group=if(manual){rep(1:xmin, times=3)}

If this modification is not necessary, then we can close this issue

Have a good trip!

Alboukadel

Thank you again for this awesome package.

Well, thank you for most its downloads :)

I found a quick fix to my issue

That's great to hear. And for your suggestion, I will have to have a more thorough look, so I will leave the issue open and take another look when I am back.

Have a good trip!

Thanks.

I found a quick fix to my issue:

  1. Adding group column: each row (i.e., comparison) is considered as a different group
  2. Specifying the group in aes()

Hi, Alboukadel, great work. It solved my problem. Thank you !

@shiyun09 you're welcome, I'm happy to know that it helps

@kassambara thank you, I run in this problem and your workaround was exactly what I needed.

I use rstatix and add manually the signf. values and it did not work when the annotations were the same. Now I use simply the p.adj column as a dummy group.

custom_p <- DATA %>% rstatix::dunn_test(costs ~ 0 + tri_size, p.adjust.method = "holm") 
custom_p <- pwc %>% rstatix::add_xy_position(x = "tri_size")
ggplot(data, aes()) + geom_boxplot() + ...
  ggsignif::geom_signif(
    data=custom_p,
    aes(xmin = xmin, xmax = xmax, annotations = p.adj.signif, y_position = y.position, group = p.adj),
    manual=TRUE)

With group:

with group

Without group:

without group

Cheers
Hannes

I am revisiting this, but I can't actually reproduce the original behavior. I am not sure if this has something to do with ggplot2 itself having changed:

library(ggplot2)
library(ggsignif)

p <- ggplot(ToothGrowth, aes(supp, len)) +
  geom_boxplot(aes(color = dose))

s <- stat.test <- data.frame(
  stringsAsFactors=FALSE,
  p.adj = c(0.000176, 3.96e-06, 0.0392, 1.36e-06, 1.4e-07, 9.16e-05),
  signif = c("****", "****", "****", "****", "****", "****"),
  signif2 = c("a", "b", "c", "d", "e", "f"),
  y_position = c(31.827, 33.5295, 35.232, 34.917, 37.1445, 39.372),
  xmin = c(0.7, 0.7, 1, 1.7, 1.7, 2),
  xmax = c(1, 1.3, 1.3, 2, 2.3, 2.3),
  group = rep(1:2, each = 3),
  supp = as.factor(rep(c("OJ", "VC"), each = 3))
)

s
#>      p.adj signif signif2 y_position xmin xmax group supp
#> 1 1.76e-04   ****       a    31.8270  0.7  1.0     1   OJ
#> 2 3.96e-06   ****       b    33.5295  0.7  1.3     1   OJ
#> 3 3.92e-02   ****       c    35.2320  1.0  1.3     1   OJ
#> 4 1.36e-06   ****       d    34.9170  1.7  2.0     2   VC
#> 5 1.40e-07   ****       e    37.1445  1.7  2.3     2   VC
#> 6 9.16e-05   ****       f    39.3720  2.0  2.3     2   VC

p + geom_signif(
  aes(xmin = xmin, xmax = xmax, y_position = y_position, annotations = signif2),
  data = stat.test, manual = TRUE, tip_length = 0
)
#> Warning: Ignoring unknown aesthetics: xmin, xmax, y_position, annotations

Created on 2021-01-13 by the reprex package (v0.3.0)

Session info
devtools::session_info()
#> โ”€ Session info โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
#>  setting  value                       
#>  version  R version 4.0.3 (2020-10-10)
#>  os       macOS Mojave 10.14.6        
#>  system   x86_64, darwin17.0          
#>  ui       X11                         
#>  language (EN)                        
#>  collate  en_US.UTF-8                 
#>  ctype    en_US.UTF-8                 
#>  tz       Europe/Berlin               
#>  date     2021-01-13                  
#> 
#> โ”€ Packages โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
#>  package     * version date       lib source        
#>  assertthat    0.2.1   2019-03-21 [1] CRAN (R 4.0.2)
#>  callr         3.5.1   2020-10-13 [1] CRAN (R 4.0.2)
#>  cli           2.2.0   2020-11-20 [1] CRAN (R 4.0.3)
#>  colorspace    2.0-0   2020-11-11 [1] CRAN (R 4.0.2)
#>  crayon        1.3.4   2017-09-16 [1] CRAN (R 4.0.2)
#>  curl          4.3     2019-12-02 [1] CRAN (R 4.0.1)
#>  desc          1.2.0   2018-05-01 [1] CRAN (R 4.0.2)
#>  devtools      2.3.2   2020-09-18 [1] CRAN (R 4.0.2)
#>  digest        0.6.27  2020-10-24 [1] CRAN (R 4.0.2)
#>  dplyr         1.0.2   2020-08-18 [1] CRAN (R 4.0.2)
#>  ellipsis      0.3.1   2020-05-15 [1] CRAN (R 4.0.2)
#>  evaluate      0.14    2019-05-28 [1] CRAN (R 4.0.1)
#>  fansi         0.4.1   2020-01-08 [1] CRAN (R 4.0.2)
#>  farver        2.0.3   2020-01-16 [1] CRAN (R 4.0.2)
#>  fs            1.5.0   2020-07-31 [1] CRAN (R 4.0.2)
#>  generics      0.1.0   2020-10-31 [1] CRAN (R 4.0.2)
#>  ggplot2     * 3.3.3   2020-12-30 [1] CRAN (R 4.0.3)
#>  ggsignif    * 0.6.0   2019-08-08 [1] CRAN (R 4.0.2)
#>  glue          1.4.2   2020-08-27 [1] CRAN (R 4.0.2)
#>  gtable        0.3.0   2019-03-25 [1] CRAN (R 4.0.2)
#>  highr         0.8     2019-03-20 [1] CRAN (R 4.0.2)
#>  htmltools     0.5.1   2021-01-12 [1] CRAN (R 4.0.3)
#>  httr          1.4.2   2020-07-20 [1] CRAN (R 4.0.2)
#>  knitr         1.30    2020-09-22 [1] CRAN (R 4.0.2)
#>  labeling      0.4.2   2020-10-20 [1] CRAN (R 4.0.2)
#>  lifecycle     0.2.0   2020-03-06 [1] CRAN (R 4.0.2)
#>  magrittr      2.0.1   2020-11-17 [1] CRAN (R 4.0.3)
#>  memoise       1.1.0   2017-04-21 [1] CRAN (R 4.0.2)
#>  mime          0.9     2020-02-04 [1] CRAN (R 4.0.2)
#>  munsell       0.5.0   2018-06-12 [1] CRAN (R 4.0.2)
#>  pillar        1.4.7   2020-11-20 [1] CRAN (R 4.0.3)
#>  pkgbuild      1.2.0   2020-12-15 [1] CRAN (R 4.0.3)
#>  pkgconfig     2.0.3   2019-09-22 [1] CRAN (R 4.0.2)
#>  pkgload       1.1.0   2020-05-29 [1] CRAN (R 4.0.2)
#>  prettyunits   1.1.1   2020-01-24 [1] CRAN (R 4.0.2)
#>  processx      3.4.5   2020-11-30 [1] CRAN (R 4.0.3)
#>  ps            1.5.0   2020-12-05 [1] CRAN (R 4.0.3)
#>  purrr         0.3.4   2020-04-17 [1] CRAN (R 4.0.2)
#>  R6            2.5.0   2020-10-28 [1] CRAN (R 4.0.2)
#>  remotes       2.2.0   2020-07-21 [1] CRAN (R 4.0.2)
#>  rlang         0.4.10  2020-12-30 [1] CRAN (R 4.0.3)
#>  rmarkdown     2.6     2020-12-14 [1] CRAN (R 4.0.3)
#>  rprojroot     2.0.2   2020-11-15 [1] CRAN (R 4.0.3)
#>  scales        1.1.1   2020-05-11 [1] CRAN (R 4.0.2)
#>  sessioninfo   1.1.1   2018-11-05 [1] CRAN (R 4.0.2)
#>  stringi       1.5.3   2020-09-09 [1] CRAN (R 4.0.2)
#>  stringr       1.4.0   2019-02-10 [1] CRAN (R 4.0.2)
#>  testthat      3.0.1   2020-12-17 [1] CRAN (R 4.0.3)
#>  tibble        3.0.4   2020-10-12 [1] CRAN (R 4.0.2)
#>  tidyselect    1.1.0   2020-05-11 [1] CRAN (R 4.0.2)
#>  usethis       2.0.0   2020-12-10 [1] CRAN (R 4.0.3)
#>  vctrs         0.3.6   2020-12-17 [1] CRAN (R 4.0.3)
#>  withr         2.3.0   2020-09-22 [1] CRAN (R 4.0.2)
#>  xfun          0.20    2021-01-06 [1] CRAN (R 4.0.3)
#>  xml2          1.3.2   2020-04-23 [1] CRAN (R 4.0.2)
#>  yaml          2.2.1   2020-02-01 [1] CRAN (R 4.0.2)
#> 
#> [1] /Users/patil/Library/R/4.0/library
#> [2] /Library/Frameworks/R.framework/Versions/4.0/Resources/library

Closing this as I can no longer reproduce this behavior. Please re-open it with a reprex if you can reproduce this issue again.

I found a way of replicating the original reprex. The variable "dose" from "ToothGrowth" needs to be a factor to enable the color mapping. I suppose the OP (@kassambara) changed "ToothGrowth" before posting.

library(ggplot2)
library(ggsignif)
p <- ggplot(ToothGrowth, aes(supp, len)) +
  geom_boxplot(aes(color = as.factor(dose)))
s <- stat.test <- data.frame(
  stringsAsFactors=FALSE,
  p.adj = c(0.000176, 3.96e-06, 0.0392, 1.36e-06, 1.4e-07, 9.16e-05),
  signif = c("****", "****", "****", "****", "****", "****"),
  signif2 = c("a", "b", "c", "d", "e", "f"),
  y_position = c(31.827, 33.5295, 35.232, 34.917, 37.1445, 39.372),
  xmin = c(0.7, 0.7, 1, 1.7, 1.7, 2),
  xmax = c(1, 1.3, 1.3, 2, 2.3, 2.3),
  group = rep(1:2, each = 3),
  supp = as.factor(rep(c("OJ", "VC"), each = 3))
)

p + geom_signif(
  aes(xmin = xmin, xmax = xmax, y_position = y_position, annotations = signif),
  data = stat.test,
  manual = TRUE, tip_length = 0
)
#> Warning: Ignoring unknown aesthetics: xmin, xmax, y_position, annotations

Created on 2021-11-09 by the reprex package (v2.0.1)

Session Info
devtools::session_info()
#> - Session info ---------------------------------------------------------------
#>  setting  value                       
#>  version  R version 4.0.5 (2021-03-31)
#>  os       Windows 10 x64              
#>  system   x86_64, mingw32             
#>  ui       RTerm                       
#>  language (EN)                        
#>  collate  Portuguese_Brazil.1252      
#>  ctype    Portuguese_Brazil.1252      
#>  tz       America/Sao_Paulo           
#>  date     2021-11-09                  
#> 
#> - Packages -------------------------------------------------------------------
#>  package     * version date       lib source        
#>  cachem        1.0.4   2021-02-13 [1] CRAN (R 4.0.5)
#>  callr         3.6.0   2021-03-28 [1] CRAN (R 4.0.4)
#>  cli           2.4.0   2021-04-05 [1] CRAN (R 4.0.5)
#>  crayon        1.4.1   2021-02-08 [1] CRAN (R 4.0.5)
#>  desc          1.3.0   2021-03-05 [1] CRAN (R 4.0.5)
#>  devtools      2.4.0   2021-04-07 [1] CRAN (R 4.0.5)
#>  digest        0.6.27  2020-10-24 [1] CRAN (R 4.0.3)
#>  ellipsis      0.3.1   2020-05-15 [1] CRAN (R 4.0.2)
#>  evaluate      0.14    2019-05-28 [1] CRAN (R 4.0.2)
#>  fastmap       1.1.0   2021-01-25 [1] CRAN (R 4.0.5)
#>  fs            1.5.0   2020-07-31 [1] CRAN (R 4.0.2)
#>  glue          1.4.2   2020-08-27 [1] CRAN (R 4.0.3)
#>  highr         0.8     2019-03-20 [1] CRAN (R 4.0.2)
#>  htmltools     0.5.1.1 2021-01-22 [1] CRAN (R 4.0.5)
#>  knitr         1.31    2021-01-27 [1] CRAN (R 4.0.5)
#>  lifecycle     1.0.0   2021-02-15 [1] CRAN (R 4.0.5)
#>  magrittr      2.0.1   2020-11-17 [1] CRAN (R 4.0.3)
#>  memoise       2.0.0   2021-01-26 [1] CRAN (R 4.0.5)
#>  pkgbuild      1.2.0   2020-12-15 [1] CRAN (R 4.0.3)
#>  pkgload       1.2.1   2021-04-06 [1] CRAN (R 4.0.5)
#>  prettyunits   1.1.1   2020-01-24 [1] CRAN (R 4.0.2)
#>  processx      3.5.1   2021-04-04 [1] CRAN (R 4.0.5)
#>  ps            1.6.0   2021-02-28 [1] CRAN (R 4.0.5)
#>  purrr         0.3.4   2020-04-17 [1] CRAN (R 4.0.2)
#>  R6            2.5.0   2020-10-28 [1] CRAN (R 4.0.3)
#>  remotes       2.3.0   2021-04-01 [1] CRAN (R 4.0.5)
#>  reprex        2.0.1   2021-08-05 [1] CRAN (R 4.0.5)
#>  rlang         0.4.10  2020-12-30 [1] CRAN (R 4.0.5)
#>  rmarkdown     2.7     2021-02-19 [1] CRAN (R 4.0.5)
#>  rprojroot     2.0.2   2020-11-15 [1] CRAN (R 4.0.3)
#>  rstudioapi    0.13    2020-11-12 [1] CRAN (R 4.0.3)
#>  sessioninfo   1.1.1   2018-11-05 [1] CRAN (R 4.0.2)
#>  stringi       1.4.6   2020-02-17 [1] CRAN (R 4.0.0)
#>  stringr       1.4.0   2019-02-10 [1] CRAN (R 4.0.2)
#>  testthat      3.0.2   2021-02-14 [1] CRAN (R 4.0.5)
#>  usethis       2.0.1   2021-02-10 [1] CRAN (R 4.0.5)
#>  withr         2.4.1   2021-01-26 [1] CRAN (R 4.0.5)
#>  xfun          0.22    2021-03-11 [1] CRAN (R 4.0.5)
#>  yaml          2.2.1   2020-02-01 [1] CRAN (R 4.0.2)
#> 
#> [1] C:/Users/mateu/Documents/R/win-library/4.0
#> [2] C:/Program Files/R/R-4.0.5/library

I agree with Alboukadel when he says that

it's a good user-experience to have this grouping done automatically

I hope to see this added/fixed soon!

Best,
Mateus.