cur_column() in mutate(across()) does not seem to iterate, when outside the .fn

Can anybody please explain to me this behaviour?

  ext_fn <- function(x, var_name) {
    var_name
  }
  
  library(dplyr)

  mtcars %>% 
    slice(1:5) %>% # just to keep it short
    mutate(across(everything(), .fns = ext_fn, var_name = cur_column()))
#>   mpg cyl disp  hp drat  wt qsec  vs  am gear carb
#> 1 mpg mpg  mpg mpg  mpg mpg  mpg mpg mpg  mpg  mpg
#> 2 mpg mpg  mpg mpg  mpg mpg  mpg mpg mpg  mpg  mpg
#> 3 mpg mpg  mpg mpg  mpg mpg  mpg mpg mpg  mpg  mpg
#> 4 mpg mpg  mpg mpg  mpg mpg  mpg mpg mpg  mpg  mpg
#> 5 mpg mpg  mpg mpg  mpg mpg  mpg mpg mpg  mpg  mpg

Created on 2020-11-01 by the reprex package (v0.3.0)

Note cur_column() does not seem to iterate, but keeps passing the value of the first column in the dataset. Is this actually the expected behaviour of cur_column() in this case? what would be the use case for this behaviour?

I do actually know how to make it work, to get my expected output. Just wrap the ext_fn in an anonymous function (in this case, using purrr-style lambda) and pass that one to .fn and use cur_column() within the anonymous fn.

  mtcars %>% 
    slice(1:5) %>% # just to keep it short
    mutate(across(everything(), .fns = ~ext_fn(.x, cur_column())))
#>   mpg cyl disp hp drat wt qsec vs am gear carb
#> 1 mpg cyl disp hp drat wt qsec vs am gear carb
#> 2 mpg cyl disp hp drat wt qsec vs am gear carb
#> 3 mpg cyl disp hp drat wt qsec vs am gear carb
#> 4 mpg cyl disp hp drat wt qsec vs am gear carb
#> 5 mpg cyl disp hp drat wt qsec vs am gear carb

Created on 2020-11-01 by the reprex package (v0.3.0)

That works. But why my original attempt of using ... to pass the cur_column() as additional arguments for the function call in .fns, just does not work.

At first glance, it seemed to me a legit approach. After all, the docs for cur_column() say:

cur_column() gives the name of the current column (in across() only).

And I was in fact using it "in across()", ..., just not within the .fn passed to across().

Most probably I am missing something here, but I cannot find a sensible use case for the observed behaviour in my original attempt. So any info would be helpful (just to soothe my mind, 'cause as shown above, I know how to get my expected output).

I think it's expected. As per ?across:

.fns Functions to apply to each of the selected columns. Possible values are:
[...]
Within these functions you can use cur_column() and cur_group() to access the current column and grouping keys respectively.

So when used within .fns, you get a dynamic value of cur_column() and cur_group() corresponding to the current context (similar to .col within the .names argument); whereas in ... you are only passing static arguments that will be the same for every call to .fns.

My expectation would have been that cur_column() should give an error when used outside of .fns, perhaps the authors could think of a use case to pass it in ....

1 Like

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.