Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dplyr:::replace_with function #17

Closed
jlegewie opened this issue Nov 8, 2016 · 3 comments
Closed

dplyr:::replace_with function #17

jlegewie opened this issue Nov 8, 2016 · 3 comments

Comments

@jlegewie
Copy link

jlegewie commented Nov 8, 2016

Moving this from tidyverse/dplyr#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.

@nickresnick
Copy link

posting the ever annoying "+1" here. Would it be great to have for things like modified dplyr::coalesce for factors.

@hadley hadley transferred this issue from r-lib/vctrs Oct 31, 2018
@DavisVaughan
Copy link
Member

DavisVaughan commented Oct 24, 2019

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

@hadley hadley mentioned this issue Nov 29, 2019
@hadley
Copy link
Member

hadley commented Nov 29, 2019

I think this is just #15? No one has supplied any examples so it's hard to know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants