Skip to content

Commit

Permalink
facet_wrap(drop = TRUE) can handle character variables with NAs (#…
Browse files Browse the repository at this point in the history
…5847)

* `ulevels()` only drops character NAs on request

* add test

* add news bullet
  • Loading branch information
teunbrand committed Apr 29, 2024
1 parent 09bcda6 commit c5a9c68
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 4 deletions.
4 changes: 4 additions & 0 deletions NEWS.md
@@ -1,5 +1,9 @@
# ggplot2 (development version)

* Prevented `facet_wrap(..., drop = FALSE)` from throwing spurious errors when
a character facetting variable contained `NA`s (@teunbrand, #5485).
* When facets coerce the faceting variables to factors, the 'ordered' class
is dropped (@teunbrand, #5666).
* `geom_curve()` now appropriately removes missing data instead of throwing
errors (@teunbrand, #5831).
* `update_geom_defaults()` and `update_stat_defaults()` have a reset mechanism
Expand Down
4 changes: 2 additions & 2 deletions R/facet-grid-.R
Expand Up @@ -511,11 +511,11 @@ FacetGrid <- ggproto("FacetGrid", Facet,

# Helpers -----------------------------------------------------------------

ulevels <- function(x) {
ulevels <- function(x, na.last = TRUE) {
if (is.factor(x)) {
x <- addNA(x, TRUE)
factor(levels(x), levels(x), exclude = NULL)
} else {
sort(unique0(x))
sort(unique0(x), na.last = na.last)
}
}
2 changes: 1 addition & 1 deletion R/stat-summary-2d.R
Expand Up @@ -126,7 +126,7 @@ StatSummary2d <- ggproto("StatSummary2d", Stat,

# Adaptation of tapply that returns a data frame instead of a matrix
tapply_df <- function(x, index, fun, ..., drop = TRUE) {
labels <- lapply(index, ulevels)
labels <- lapply(index, ulevels, na.last = NA) # drop NA
out <- expand.grid(labels, KEEP.OUT.ATTRS = FALSE, stringsAsFactors = FALSE)

grps <- split(x, index)
Expand Down
8 changes: 7 additions & 1 deletion tests/testthat/test-facet-layout.R
Expand Up @@ -100,7 +100,8 @@ test_that("grid: as.table reverses rows", {

a2 <- data_frame(
a = factor(1:3, levels = 1:4),
b = factor(1:3, levels = 4:1)
b = factor(1:3, levels = 4:1),
c = as.character(c(1:2, NA))
)

test_that("wrap: drop = FALSE preserves unused levels", {
Expand All @@ -111,6 +112,11 @@ test_that("wrap: drop = FALSE preserves unused levels", {
wrap_b <- panel_layout(facet_wrap(~b, drop = FALSE), list(a2))
expect_equal(nrow(wrap_b), 4)
expect_equal(as.character(wrap_b$b), as.character(4:1))

# NA character should not be dropped or throw errors #5485
wrap_c <- panel_layout(facet_wrap(~c, drop = FALSE), list(a2))
expect_equal(nrow(wrap_c), 3)
expect_equal(wrap_c$c, a2$c)
})

test_that("grid: drop = FALSE preserves unused levels", {
Expand Down

0 comments on commit c5a9c68

Please sign in to comment.