Skip to content

Commit 1f6f0cb

Browse files
authored
Allow empty annotations. (#3320)
* allow empty annotations. fixes #3317 * fix corner case where all annotation parameters have length 1 * add unit tests, simplify code; closes #3314 * improve comments * simplify code calculating number of rows in annotation data frame
1 parent 8406115 commit 1f6f0cb

File tree

3 files changed

+45
-5
lines changed

3 files changed

+45
-5
lines changed

R/annotation.r

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,22 @@ annotate <- function(geom, x = NULL, y = NULL, xmin = NULL, xmax = NULL,
4646

4747
# Check that all aesthetic have compatible lengths
4848
lengths <- vapply(aesthetics, length, integer(1))
49-
unequal <- length(unique(setdiff(lengths, 1L))) > 1L
50-
if (unequal) {
49+
n <- unique(lengths)
50+
51+
# if there is more than one unique length, ignore constants
52+
if (length(n) > 1L) {
53+
n <- setdiff(n, 1L)
54+
}
55+
56+
# if there is still more than one unique length, we error out
57+
if (length(n) > 1L) {
5158
bad <- lengths != 1L
5259
details <- paste(names(aesthetics)[bad], " (", lengths[bad], ")",
5360
sep = "", collapse = ", ")
5461
stop("Unequal parameter lengths: ", details, call. = FALSE)
5562
}
5663

57-
data <- new_data_frame(position, n = max(lengths))
64+
data <- new_data_frame(position, n = n)
5865
layer(
5966
geom = geom,
6067
params = list(

R/performance.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ new_data_frame <- function(x = list(), n = NULL) {
44
if (length(x) != 0 && is.null(names(x))) stop("Elements must be named", call. = FALSE)
55
lengths <- vapply(x, length, integer(1))
66
if (is.null(n)) {
7-
n <- if (length(x) == 0) 0 else max(lengths)
7+
n <- if (length(x) == 0 || min(lengths) == 0) 0 else max(lengths)
88
}
99
for (i in seq_along(x)) {
1010
if (lengths[i] == n) next
@@ -32,7 +32,7 @@ split_matrix <- function(x, col_names = colnames(x)) {
3232
if (!is.null(col_names)) names(x) <- col_names
3333
x
3434
}
35-
35+
3636
mat_2_df <- function(x, col_names = colnames(x)) {
3737
new_data_frame(split_matrix(x, col_names))
3838
}

tests/testthat/test-performance.R

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
context("Performance related alternatives")
22

3+
# modify_list() -----------------------------------------------------------
4+
35
testlist <- list(
46
a = 5.5,
57
b = "x",
@@ -32,3 +34,34 @@ test_that("modify_list erases null elements", {
3234
expect_null(res$c)
3335
expect_named(res, c('a', 'b', 'd'))
3436
})
37+
38+
39+
# new_data_frame() --------------------------------------------------------
40+
41+
test_that("new_data_frame handles zero-length inputs", {
42+
# zero-length input creates zero-length data frame
43+
d <- new_data_frame(list(x = numeric(0), y = numeric(0)))
44+
expect_equal(nrow(d), 0L)
45+
46+
# constants are ignored in the context of zero-length input
47+
d <- new_data_frame(list(x = numeric(0), y = numeric(0), z = 1))
48+
expect_equal(nrow(d), 0L)
49+
50+
# vectors of length > 1 don't mix with zero-length input
51+
expect_error(
52+
new_data_frame(list(x = numeric(0), y = numeric(0), z = 1, a = c(1, 2))),
53+
"Elements must equal the number of rows or 1"
54+
)
55+
56+
# explicit recycling doesn't work with zero-length input
57+
expect_error(
58+
new_data_frame(list(x = numeric(0), z = 1), n = 5),
59+
"Elements must equal the number of rows or 1"
60+
)
61+
# but it works without
62+
d <- new_data_frame(list(x = 1, y = "a"), n = 5)
63+
expect_equal(nrow(d), 5L)
64+
expect_identical(d$x, rep(1, 5L))
65+
expect_identical(d$y, rep("a", 5L))
66+
67+
})

0 commit comments

Comments
 (0)