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

rename_with with empty column selection fails w/ dplyr 1.1.0. #6688

Closed
lschneiderbauer opened this issue Feb 6, 2023 · 4 comments · Fixed by #6690
Closed

rename_with with empty column selection fails w/ dplyr 1.1.0. #6688

lschneiderbauer opened this issue Feb 6, 2023 · 4 comments · Fixed by #6690

Comments

@lschneiderbauer
Copy link

Hi,

due to the size check in the new dplyr version, dplyr 1.1.0, renames with empty column selections don't work anymore (since it expects a vector of functions of size 0).
This is of course not a big problem when used interactively, since one can simply omit the whole statement.
But when used programmatically in a data pipeline it forces the programmer to always treat this case separately (if for instance the .cols argument is defined by external dynamical parameters).

I would expect this function to simply do nothing if no columns are selected, and not throw an error.

library(dplyr, warn.conflicts = FALSE)

tibble(col = c(1,3)) %>%
  rename_with(
    .cols = contains("test"),
    .fn = ~ paste0("blah.", .)
  )
#> Error in `rename_with()`:
#> ! `.fn` must return a vector of length 0, not 1.

#> Backtrace:
#>     ▆
#>  1. ├─tibble(col = c(1, 3)) %>% ...
#>  2. ├─dplyr::rename_with(...)
#>  3. └─dplyr:::rename_with.data.frame(., .cols = contains("test"), .fn = ~paste0("blah.", .))
#>  4.   └─cli::cli_abort("{.arg .fn} must return a vector of length {length(sel)}, not {length(new)}.")
#>  5.     └─rlang::abort(...)

Created on 2023-02-06 with reprex v2.0.2

@lschneiderbauer
Copy link
Author

Apparently, the following example is working:

library(dplyr, warn.conflicts = FALSE)

tibble(col = c(1,3)) %>%
  rename_with(
    .cols = contains("test"),
    .fn = toupper
  )
#> # A tibble: 2 × 1
#>     col
#>   <dbl>
#> 1     1
#> 2     3

Created on 2023-02-06 with reprex v2.0.2

I don't understand why though.

@lschneiderbauer
Copy link
Author

Okay, I think, I get it now.
The problem is that ~ paste0("blah.", .) returns a vector of length 1 even if the argument is a vector of length zero.

In this case, the behavior seems actually fine and consistent to me.
I just need to find a proper substitute for ~ paste0("blah.", .).

Sorry for the noise.

@hadley
Copy link
Member

hadley commented Feb 6, 2023

Technically that's a bug with paste0():

library(dplyr, warn.conflicts = FALSE)

df <- tibble(col = c(1, 3))

df |>
  rename_with(
    .cols = contains("test"),
    .fn = ~ paste0("blah.", ., recycle0 = TRUE)
  )
#> # A tibble: 2 × 1
#>     col
#>   <dbl>
#> 1     1
#> 2     3
df |>
  rename_with(
    .cols = contains("test"),
    .fn = ~ stringr::str_c("blah.", .)
  )
#> # A tibble: 2 × 1
#>     col
#>   <dbl>
#> 1     1
#> 2     3

Created on 2023-02-06 with reprex v2.0.2

So I'm not sure how we should handle this in dplyr.

@mrainers
Copy link

mrainers commented Apr 18, 2023

It's the same with stringr::str_c(). The dplyr update change broke my script :-( Now I have to do extra checks if the variable selection return an empty result to handle this error. (Edit: Will use the example in the manual)

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

Successfully merging a pull request may close this issue.

3 participants