diff --git a/NEWS.md b/NEWS.md index 0468fe30be..4e0cfd14f2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -12,6 +12,7 @@ * Closed #2208: `ggplotly()` no longer errors given a `geom_area()` with 1 or less data points (error introduced by new behavior in ggplot2 v3.4.0). (#2209) * Closed #2220: `ggplotly()` no longer errors on `stat_summary(geom = "crossbar")`. (#2222) * Closed #2212: `ggplotly()` no longer removes legends when setting guide properties via `guides(aes = guide_xxx(...))`. +* Closed #1947: `ggplotly()` now correctly handles `geom_vline`/`geom_hline` with empty data. Previously, if `geom_vline`/`geom_hline` was passed an empty data frame, it would result in an error. The plot is drawn even if no lines are found; this is the same behavior as `ggplot2`. # 4.10.1 diff --git a/R/layers2traces.R b/R/layers2traces.R index 5b110cd56e..7757f94319 100644 --- a/R/layers2traces.R +++ b/R/layers2traces.R @@ -445,7 +445,9 @@ to_basic.GeomHline <- function(data, prestats_data, layout, params, p, ...) { data = layout$layout, cols = paste0(x, c("_min", "_max")), values_to = x, names_to = "variable" ) lay <- as.data.frame(lay) - data <- merge(lay[c("PANEL", x)], data, by = "PANEL") + if (nrow(data) > 0) { + data <- merge(lay[c("PANEL", x)], data, by = "PANEL") + } data[["x"]] <- data[[x]] data[["y"]] <- data$yintercept prefix_class(data, c("GeomHline", "GeomPath")) @@ -462,7 +464,9 @@ to_basic.GeomVline <- function(data, prestats_data, layout, params, p, ...) { data = layout$layout, cols = paste0(y, c("_min", "_max")), values_to = y, names_to = "variable" ) lay <- as.data.frame(lay) - data <- merge(lay[c("PANEL", y)], data, by = "PANEL") + if (nrow(data) > 0) { + data <- merge(lay[c("PANEL", y)], data, by = "PANEL") + } data[["y"]] <- data[[y]] data[["x"]] <- data$xintercept prefix_class(data, c("GeomVline", "GeomPath")) diff --git a/tests/testthat/test-ggplot-hline.R b/tests/testthat/test-ggplot-hline.R index 9ed7af92a6..ba41144e50 100644 --- a/tests/testthat/test-ggplot-hline.R +++ b/tests/testthat/test-ggplot-hline.R @@ -97,3 +97,8 @@ test_that("hline works with coord_flip", { expect_equivalent(l$data[[2]]$x, c(5, 5)) expect_equivalent(l$data[[2]]$y, c(5.95, 6.05)) }) + +test_that("geom_vline/geom_hline does not throw an error with ggplotly when no lines are found", { + p3 <- ggplot(df) + geom_hline(aes(yintercept = x), data = data.frame(x = 1)[F, , drop = FALSE]) + expect_error(plotly::ggplotly(p3), NA) +}) diff --git a/tests/testthat/test-ggplot-vline.R b/tests/testthat/test-ggplot-vline.R index ceda7e1dfa..0829974f1f 100644 --- a/tests/testthat/test-ggplot-vline.R +++ b/tests/testthat/test-ggplot-vline.R @@ -46,3 +46,8 @@ test_that("vline works with coord_flip", { expect_equivalent(l$data[[2]]$x, c(5.95, 6.05)) expect_equivalent(l$data[[2]]$y, c(5, 5)) }) + +test_that("geom_vline/geom_hline does not throw an error with ggplotly when no lines are found", { + p <- ggplot(df) + geom_vline(aes(xintercept = x), data = data.frame(x = 1)[F, , drop = FALSE]) + expect_error(plotly::ggplotly(p), NA) +})