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

across() fails silently when using .funs (used in scoped mutate) instead of .fns #6638

Closed
m-sostero opened this issue Jan 12, 2023 · 3 comments · Fixed by #6646
Closed

across() fails silently when using .funs (used in scoped mutate) instead of .fns #6638

m-sostero opened this issue Jan 12, 2023 · 3 comments · Fixed by #6646

Comments

@m-sostero
Copy link

across() uses .fns = as the argument to supply an anonymous function.
This is different than the scoped mutate functions, which used .funs =, with an extra "u".

This causes some problems when rewriting code from scoped syntax mutate_at(.funs = ~) to the new mutate(across(.fns = ~)), because supplying the wrong argument in across() (namely, .funs instead of .fns) fails silently, as shown below.

library(tidyverse)

mtcars <- as_tibble(mtcars) %>% select(mpg)

# Using the named argument ".fns" applies the function, as expected
mtcars %>% mutate(across(mpg, .fns = ~ . * 1000))
#> # A tibble: 32 × 1
#>      mpg
#>    <dbl>
#>  1 21000
#>  2 21000
#>  3 22800
#>  4 21400
#>  5 18700
#>  6 18100
#>  7 14300
#>  8 24400
#>  9 22800
#> 10 19200
#> # … with 22 more rows

# Using the named argument ".funs" fails, silently
mtcars %>% mutate(across(mpg, .funs = ~ . * 1000))
#> # A tibble: 32 × 1
#>      mpg
#>    <dbl>
#>  1  21  
#>  2  21  
#>  3  22.8
#>  4  21.4
#>  5  18.7
#>  6  18.1
#>  7  14.3
#>  8  24.4
#>  9  22.8
#> 10  19.2
#> # … with 22 more rows

Created on 2023-01-12 by the reprex package (v2.0.1)

As the argument is ignored, the result is no different than failing to supply any function at all.
(Supplying the function without naming the argument works as expected.)

Perhaps across should throw a warning when it does not detect an anonymous function being supplied?

@hadley
Copy link
Member

hadley commented Jan 12, 2023

You get a warning in the dev version:

library(tidyverse)
x <- mtcars %>% mutate(across(mpg, .funs = ~ . * 1000))
#> Warning: There was 1 warning in `mutate()`.
#> ℹ In argument: `across(mpg, .funs = ~. * 1000)`.
#> Caused by warning:
#> ! The `...` argument of `across()` is deprecated as of dplyr 1.1.0.
#> Supply arguments directly to `.fns` through an anonymous function instead.
#> 
#>   # Previously
#>   across(a:b, mean, na.rm = TRUE)
#> 
#>   # Now
#>   across(a:b, \(x) mean(x, na.rm = TRUE))

Created on 2023-01-12 with reprex v2.0.2

It's not exactly the most direct warning, but it's valid to use across() with .fns so maybe this is enough.

I guess we could be even stricter and error if .fns is not supplied and ... is.

@m-sostero
Copy link
Author

Thank you! Indeed, the warning is quite indirect (especially for such a subtle one-letter difference, for a spelling that is accepted elsewhere), but at least it prompts further inspection.
What would be a use-case for not supplying any .fns in across()?

@hadley
Copy link
Member

hadley commented Jan 12, 2023

@m-sostero as documented, to just retrieve a raw data frame (for which pick() is the now preferred syntax)

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.

2 participants