0

I'm attempting to iterate over a list of column suffixes and, for each, call a function to perform a bunch of summarises. My problem is how to correctly build the variable name and have R interpret it correctly. I've tried various combinations of {{}}, !!, and sym() without success.

I can do this for the LHS in a mutate without problems, but the correct syntax for the RHS seems to elude me.

A stripped down version follows:

fsumm = function(data, lookAhead) {
    summarise(data, 
              mean=mean("prefix{lookAhead}", na.rm=TRUE),
             )   
 }


lookAheadList = c(2, 5, 10, 20)
 
for (lookAhead in lookAheadList) {
  p = df %>% 
    fsumm( lookAhead ) 
  print(p)
}

UPDATE: I seem to be making some progress by using:

summarise( mean=mean( !!sym(glue("prefix{lookAhead}")), na.rm=TRUE) )

I thought though that tidyval(?) was meant to allow me to drop the explicit call to glue(). Is there a simpler way of writing this?

Ian
  • 1,507
  • 3
  • 21
  • 36
  • 1
    It's easier to help you if you include a simple [reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) with sample input and desired output that can be used to test and verify possible solutions. – MrFlick Dec 20 '21 at 20:40
  • Thanks for your response. Normally, I'd agree with you, but as this question is about syntax only I think it might be a distraction here. – Ian Dec 20 '21 at 21:41
  • Well I don’t know what you are passing to these functions. Are you passing string? Quosures? Expressions? Exprs? Even if it’s just about syntax, we need a case where we can test the syntax to verify that it works as expected. – MrFlick Dec 20 '21 at 21:44
  • Ah, now understand your concern. Example of variable included. – Ian Dec 20 '21 at 21:47
  • 1
    If you want to work with building names with strings, try using the `.data` pronoun instead. For example: `summarise(data, mean=mean(.data[[paste0("prefix", lookAhead)]], na.rm=TRUE))` might do the trick. – MrFlick Dec 20 '21 at 22:26

1 Answers1

1

The following seems to work. Not sure if it's the very best solution, or not:

fsumm = function(data, lookAhead) {
  colnm = sym( glue("maxCloseGainPctNext{lookAhead}") )
  
  data %>% 
    summarise( ...
              "mean({{lookAhead}})"  := mean({{colnm}}, na.rm=TRUE), 
Ian
  • 1,507
  • 3
  • 21
  • 36
  • I think the `lookAhead` in the LHS should be within a single `{`, see https://rlang.r-lib.org/reference/glue-operators.html – Lionel Henry Dec 21 '21 at 08:01
  • Also you should use `!!` instead of `{{` with local objects. `{{` is for function arguments. I wish we could make it an error, unfortunately we can't https://rlang.r-lib.org/reference/topic-embrace-non-args.html – Lionel Henry Dec 21 '21 at 08:02
  • @LionelHenry Many thanks for those comments. Every time I prise the lid back from R and peer inside I realise I know so very little. In respect of !!, your first reference also states "As we are now moving away from !! for common tasks...". Not sure which is up to date. – Ian Dec 21 '21 at 13:09
  • My use of the {{...}} on the LHS comes from https://cran.r-project.org/web/packages/dplyr/vignettes/programming.html (search for "my_summarise4 "). Is that not correct? – Ian Dec 21 '21 at 13:16
  • In this case `lookAhead` contains a string, you don't want to inject the code typed by the user but the string itself. I.e. you need a `{` operation, not a `{{`. – Lionel Henry Dec 21 '21 at 13:48
  • It is true that we try to avoid `!!` for common tasks. So instead of `!!` you can use `.data[[colnm]]`. Good point. So altogether this is: `"mean({lookAhead})" := mean(.data[[colnm]], na.rm = TRUE)`. Oh and in this case remove the `sym()`, `.data[[foo]]` takes strings rather than symbols (although IIRC it works with both, but better keep it simple). – Lionel Henry Dec 21 '21 at 13:51
  • Yikes. Really? That is really ugly. – Ian Dec 21 '21 at 17:22
  • What's ugly about subsetting a pronoun to retrieve a colomn and using glue syntax to create strings? If you prefer `!!`, use `!!data_sym(colnm)` instead of `.data[[colnm]]`, but that's a bit roundabout. See https://rlang.r-lib.org/reference/sym.html. – Lionel Henry Dec 23 '21 at 11:46