Curly braces syntax in R

One of my R scripts has a line of code in the following syntax (simplified into a reprex) which I discovered from a Stack Overflow thread.

library(tidyverse, warn.conflicts = FALSE)
#> Warning: package 'ggplot2' was built under R version 3.6.3
#> Warning: package 'tibble' was built under R version 3.6.3
#> Warning: package 'dplyr' was built under R version 3.6.3
#> Warning: package 'forcats' was built under R version 3.6.3

expand_grid(x = c(1, 3, 9), y = c(4, 6, 2)) %>% 
  { map2(.$x, .$y, sum) }
#> [[1]]
#> [1] 5
#> 
#> [[2]]
#> [1] 7
#> 
#> [[3]]
#> [1] 3
#> 
#> [[4]]
#> [1] 7
#> 
#> [[5]]
#> [1] 9
#> 
#> [[6]]
#> [1] 5
#> 
#> [[7]]
#> [1] 13
#> 
#> [[8]]
#> [1] 15
#> 
#> [[9]]
#> [1] 11

Created on 2020-04-06 by the reprex package (v0.3.0)

I'm generating all possible combinations of two input variables and passing them as arguments to a custom function. This gives me the desired result but I don't really understand what the curly braces do and how this differs from "normal" ways of writing piped code in the tidyverse. Can someone explain?

And is this really an elegant approach? Can this be re-written in a better way?

You "escape" that expand_grid(x = c(1, 3, 9), y = c(4, 6, 2)) will be directly passed to the map2 function.
Instead, you can reference it with ..

In this case it is used to be able to reference the object twice: with .$x and .$y.

Example:

1:2 %>% {mean(c(.[1], .[2]))}
[1] 1.5
1:2 %>% mean
[1] 1.5

I see. So { } allows the entire object to be passed "as-is" to the next function in the pipe. I suppose this is useful when functions do not have data as their first argument (such as map2() in this case).

Can you suggest a way of re-writing my code without use of the { }?

2 Likes

You can find purrr::pmap useful

library(tidyverse, warn.conflicts = FALSE)

expand_grid(x = c(1, 3, 9), y = c(4, 6, 2)) %>% 
  pmap(sum)
#> [[1]]
#> [1] 5
#> 
#> [[2]]
#> [1] 7
#> 
#> [[3]]
#> [1] 3
#> 
#> [[4]]
#> [1] 7
#> 
#> [[5]]
#> [1] 9
#> 
#> [[6]]
#> [1] 5
#> 
#> [[7]]
#> [1] 13
#> 
#> [[8]]
#> [1] 15
#> 
#> [[9]]
#> [1] 11

Created on 2020-04-06 by the reprex package (v0.3.0.9001)

Hi,
Is it possible to have this output as a dataframe, not as a list ?

See ?pmap: There are two flavors that produce data frames.

1 Like

@cderv Thank you so much! I initially got an error after replacing map2() with pmap() but after re-reading Hadley's chapter on Functionals, I realized that the column names of the input tibble must match the parameter names defined in the function. That did the trick. :smile:

1 Like

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