Closed jlegewie closed 4 years ago
posting the ever annoying "+1" here. Would it be great to have for things like modified dplyr::coalesce
for factors.
Was thinking about vec_coalesce()
today so I figured I'd add this in
If we don't like using the common type and common size, then I think the signature should be vec_coalesce(x, ...)
to indicate that we are using the size/type of x
.
This is one place it would be nice for vec_slice <-
to know how to not recycle length 1 inputs and instead use them repeatedly
library(rlang)
library(vctrs)
vec_coalesce <- function(..., .ptype = NULL) {
args <- list2(...)
n_args <- vec_size(args)
if (n_args == 0L) {
return(NULL)
}
if (n_args == 1L) {
out <- args[[1L]]
return(out)
}
args <- vec_cast_common(!!! args, .to = .ptype)
args <- vec_recycle_common(!!! args)
out <- args[[1L]]
args <- args[-1L]
for (arg in args) {
is_na <- vec_equal_na(out)
if (!any(is_na)) {
break
}
vec_slice(out, is_na) <- vec_slice(arg, is_na)
}
out
}
vec_coalesce()
#> NULL
vec_coalesce(1, 0)
#> [1] 1
vec_coalesce(1, FALSE, .ptype = logical())
#> [1] TRUE
vec_coalesce(NA, 1)
#> [1] 1
vec_coalesce(c(1, NA, 2), 0L)
#> [1] 1 0 2
vec_coalesce(
data.frame(x = c(1, NA, 3)),
data.frame(x = 2)
)
#> x
#> 1 1
#> 2 2
#> 3 3
# a bit odd, but this technically makes sense
vec_coalesce(
data.frame(x = c(1, NA)),
data.frame(x = 2, y = 3)
)
#> x y
#> 1 1 NA
#> 2 2 3
vec_coalesce(
factor(c("x", "y", NA, "x", NA)),
factor("MISSING!")
)
#> [1] x y MISSING! x MISSING!
#> Levels: x y MISSING!
# Common size is used as the reference
vec_coalesce(
1,
c(1, 2, 3)
)
#> [1] 1 1 1
vec_coalesce(
NA,
c(1, 2, 3)
)
#> [1] 1 2 3
I think this is just #15? No one has supplied any examples so it's hard to know.
Moving this from https://github.com/hadley/dplyr/issues/2040
I think dplyr:::replace_with can be useful and should be exported... if_else uses it, coalesce uses it and probably other internal functions as well. It's a useful way to recode data even though similar things can be achieved with if_else.
It should work with typed NAs though but #2038 covers that, I think.