Skip to content

Commit 84c203a

Browse files
DanRudermanhadley
authored andcommitted
Fixed bug in geom-violin.r when quantiles requested but data have no range. (#1687)
* Fixed bug in geom-violin.r when quantiles requested but data have no range. * Updated NEWS.md and added unit test.
1 parent 95f4346 commit 84c203a

File tree

3 files changed

+27
-8
lines changed

3 files changed

+27
-8
lines changed

NEWS.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@
4646
* Fix bug that resulted in several annotation_x function not getting drawn when
4747
global data was lacking (#1655)
4848

49+
* Fixed problem with `geom_violin()` when quantiles requested but data
50+
have no range. Added unit test. (#1687)
51+
4952
# ggplot2 2.1.0
5053

5154
## New features
@@ -81,9 +84,9 @@
8184

8285
* `bins = n` now gives a histogram with `n` bins, not `n + 1` (#1487).
8386

84-
## Bug fixes
87+
## Bug fixes
8588

86-
* All `\donttest{}` examples run.
89+
* All `\donttest{}` examples run.
8790

8891
* All `geom_()` and `stat_()` functions now have consistent argument order:
8992
data + mapping, then geom/stat/position, then `...`, then specific arguments,

R/geom-violin.r

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,8 @@ GeomViolin <- ggproto("GeomViolin", Geom,
126126
# Needed for coord_polar and such
127127
newdata <- rbind(newdata, newdata[1,])
128128

129-
# Draw quantiles if requested
130-
if (length(draw_quantiles) > 0) {
129+
# Draw quantiles if requested, so long as there is non-zero y range
130+
if (length(draw_quantiles) > 0 & !scales::zero_range(range(data$y))) {
131131
stopifnot(all(draw_quantiles >= 0), all(draw_quantiles <= 1))
132132

133133
# Compute the quantile segments and combine with existing aesthetics
@@ -163,11 +163,11 @@ create_quantile_segment_frame <- function(data, draw_quantiles) {
163163
ecdf <- stats::approxfun(dens, data$y)
164164
ys <- ecdf(draw_quantiles) # these are all the y-values for quantiles
165165

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

170-
# We have two rows per segment drawn. Each segments gets its own group.
170+
# We have two rows per segment drawn. Each segment gets its own group.
171171
data.frame(
172172
x = interleave(violin.xminvs, violin.xmaxvs),
173173
y = rep(ys, each = 2),

tests/testthat/test-geom-violin.R

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,26 @@ test_that("", {
1818
# create_quantile_segment_frame -------------------------------------------------
1919

2020
test_that("create_quantile_segment_frame functions for 3 quantiles", {
21-
density.data <- data.frame(y=(1:256)/256, density=1/256) # uniform density
21+
density.data <- data.frame(y = (1:256)/256, density = 1/256) # uniform density
2222

2323
qs <- c(0.25, 0.5, 0.75) # 3 quantiles
2424
expect_equal(create_quantile_segment_frame(density.data, qs)$y,
25-
rep(qs, each=2))
25+
rep(qs, each = 2))
26+
})
27+
28+
test_that("quantiles do not fail on zero-range data", {
29+
zero.range.data <- data.frame(y = rep(1,3))
30+
p <- ggplot(zero.range.data) + geom_violin(aes(1, y), draw_quantiles = 0.5)
31+
32+
# This should return without error and have length one
33+
expect_equal(length(layer_grob(p)), 1)
34+
35+
# All rows should be identical in layer_data, with some specific values
36+
unique.layer.data <- unique(layer_data(p))
37+
expect_equal(nrow(unique.layer.data), 1)
38+
expect_equal(unique.layer.data$density, 0.55216039)
39+
expect_equal(unique.layer.data$count, 1.65648117)
40+
expect_equal(unique.layer.data$xmin, 0.55)
41+
expect_equal(unique.layer.data$xmax, 1.45)
2642
})
2743

0 commit comments

Comments
 (0)