Skip to content

collapsing to unique 'x' values in geom_violin with draw_quantiles #4455

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
bersbersbers opened this issue Apr 28, 2021 · 7 comments · Fixed by #4654
Closed

collapsing to unique 'x' values in geom_violin with draw_quantiles #4455

bersbersbers opened this issue Apr 28, 2021 · 7 comments · Fixed by #4654
Labels
layers 📈 messages requests for improvements to error, warning, or feedback messages

Comments

@bersbersbers
Copy link
Contributor

bersbersbers commented Apr 28, 2021

I receive the warning

In regularize.values(x, y, ties, missing(ties), na.rm = na.rm) :
  collapsing to unique 'x' values

with this code:

df <- data.frame(x = 1, y = c(0, 0.25, 0.5, 0.75, 5))
ggplot2::ggplot(df, ggplot2::aes(x = x, y = y)) +
    ggplot2::geom_violin(draw_quantiles = c(0.5))

The warning does not appear with

df <- data.frame(x = 1, y = c(0, 0.25, 0.5, 0.75, 4))

so it is not a problem of the structure (including any potential duplicates) of the data.

R version 4.0.5 (2021-03-31)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19043)

Matrix products: default

locale:
[1] LC_COLLATE=English_United States.1252
[2] LC_CTYPE=English_United States.1252
[3] LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C
[5] LC_TIME=English_United States.1252

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base

other attached packages:
[1] glue_1.4.2

loaded via a namespace (and not attached):
 [1] fansi_0.4.2      digest_0.6.27    assertthat_0.2.1 dplyr_1.0.5
 [5] utf8_1.1.4       crayon_1.4.1     grid_4.0.5       R6_2.5.0
 [9] DBI_1.1.1        lifecycle_1.0.0  gtable_0.3.0     magrittr_2.0.1
[13] scales_1.1.1     ggplot2_3.3.3    pillar_1.5.1     rlang_0.4.10
[17] farver_2.1.0     generics_0.1.0   vctrs_0.3.6      ellipsis_0.3.1
[21] labeling_0.4.2   purrr_0.3.4      munsell_0.5.0    compiler_4.0.5
[25] pkgconfig_2.0.3  colorspace_2.0-0 tidyselect_1.1.0 tibble_3.1.0
@bersbersbers
Copy link
Contributor Author

See also https://stackoverflow.com/q/67298243/

@bersbersbers
Copy link
Contributor Author

bersbersbers commented Apr 28, 2021

Here's a symmetric example.

df <- data.frame(x = 1, y = c(0, 0, 5, 10, 10))
ggplot2::ggplot(df, ggplot2::aes(x = x, y = y)) +
    ggplot2::geom_violin(draw_quantiles = c(0.5), bw = 0.1)

Also, see https://stackoverflow.com/questions/67298243/what-does-collapsing-to-unique-x-values-mean-in-this-example?noredirect=1#comment118969776_67298243

@bersbersbers
Copy link
Contributor Author

bersbersbers commented Apr 28, 2021

adjust seems to be able solve this:

df <- data.frame(x = 1, y = c(0, 0.25, 0.5, 0.75, 5))
ggplot2::ggplot(df, ggplot2::aes(x = x, y = y)) +
    ggplot2::geom_violin(draw_quantiles = c(0.5), adjust=1.1)

Should the warning maybe be turned into a more useful warning hinting the user at adjust?

@bersbersbers
Copy link
Contributor Author

bersbersbers commented Apr 29, 2021

I think quantitively, this only makes a difference, if ever, when the quantile is in a region of zero density, in which case its exact placement is not visible anyway. So it would be safe to use

ecdf <- stats::approxfun(dens, data$y, ties = "ordered")

to get rid of this warning, as in

create_quantile_segment_frame <- function(data, draw_quantiles) {
  dens <- cumsum(data$density) / sum(data$density)
  ecdf <- stats::approxfun(dens, data$y, ties = "ordered")
  ys <- ecdf(draw_quantiles) # these are all the y-values for quantiles

  # Get the violin bounds for the requested quantiles.
  violin.xminvs <- (stats::approxfun(data$y, data$xminv))(ys)
  violin.xmaxvs <- (stats::approxfun(data$y, data$xmaxv))(ys)

  # We have two rows per segment drawn. Each segment gets its own group.
  ggplot2:::new_data_frame(list(
    x = ggplot2:::interleave(violin.xminvs, violin.xmaxvs),
    y = rep(ys, each = 2),
    group = rep(ys, each = 2)
  ))
}
assignInNamespace("create_quantile_segment_frame", create_quantile_segment_frame, "ggplot2")


df <- data.frame(x = 1, y = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10))
ggplot2::ggplot(df, ggplot2::aes(x = x, y = y)) +
    ggplot2::geom_violin(draw_quantiles = c(0.5), bw = 0.1)

@thomasp85
Copy link
Member

Would you be interested in providing a PR that fixes this?

@thomasp85 thomasp85 added layers 📈 messages requests for improvements to error, warning, or feedback messages labels Oct 29, 2021
@bersbersbers
Copy link
Contributor Author

@thomasp85 sure! I still have to think about the best way to test this, but I think I know how to approach it.

@bersbersbers
Copy link
Contributor Author

@thomasp85 #4654 is ready for review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
layers 📈 messages requests for improvements to error, warning, or feedback messages
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants