Functional programming: applicability of parameters (.x) and (.) in purrr :: map

5

I am migrating to the package purrr , mainly in relation to the use of the map function. But, I'm having a hard time understanding the concepts of functional programming in purrr .

I would like to learn to apply the (.x) and (.) arguments to map instead of using function(x) with the apply family.

More precisely,

  • In what contexts use (.x) and (.) ?

  • (.x) and (.) are definite substitutes for function(x) ?

  • How to use (.x) and (.) in other packages and functions, such as dplyr::mutate ?

In order to demonstrate my difficulty, I try to write the following function in a map with (.x) and (.) , which I only get with function(x) :

library(tidyverse)

map(1:10,function(x){
  names<-str_c('var',x)
  assign(names,runif(30,20,100),envir=.GlobalEnv)
})

I have tried several configurations with map and (.x) and (.) , but only error messages are generated.

    
asked by anonymous 04.01.2019 / 16:36

1 answer

6

The functions of purrr have the following syntax:

map(vetor_ou_lista, funcao)

Next he does apply funcao to each element of vetor_ou_lista .

funcao can be any function of R or an anonymous function, as in its example.

Anonymous functions like formulas

However, purrr provides an alternate syntax for creating anonymous functions.

This syntax works as follows:

map(vetor_ou_lista, ~mean(.x + 2))

In this case, the formula ~mean(.x +2)) is equivalent to using as argument a function like this:

function(.x) {
  mean(.x + 2)
}
  

Note ~ is important to indicate that you are using the alternate syntax. This has to do with purrr .

The case of .

Since . comes from the pipe operator ( %>% ). By default the pipe passes the object to the left as the first argument of the function to its right, but we can change this behavior using . , for example:

TRUE %>% mean(x = 1:10, na.rm = .)

In the above case we are passing . ( TRUE ) to argument na.rm of function mean .

Another interesting and unintuitive behavior is that if you use the. within a call nested inside the right function, it will still use the left object as the first argument on the right. For example:

1:10 %>% cor(y  = rev(.))
#> -1

Notice that in this case he computes the correlation of x with rev (x), which would not have occurred if we did:

1:10 %>% cor(y  = .)
Error in is.data.frame(x) : argument "x" is missing, with no default

So we can use this behavior also with purrr, since map is a function of R like any other. This may then work:

mtcars %>% keep(names(.) %in% c("gear", "carb"))

See here, I do not use ~ , since I'm returning a vector of TRUE and FALSE's.

Its function

In the case of your function, I think it would be ideal to do something like this:

1:10 %>% 
  str_c("var", .) %>% 
  map(~assign(.x, runif(30,20,100),envir=.GlobalEnv))

Other packages

From version 0.8.0 of dplyr (which has not yet been for CRAN, but is in Github) you can use this syntax in the functions mutate_* , summarise_* , etc.

In version 0.8 you can do this, for example:

mtcars %>% mutate_at(c("cyl", "gear"), ~.x + 1e6)

Until earlier versions, the way dplyr was a bit different because it used the funs function:

mtcars %>% mutate_at(vars(cyl, gear), funs(. + 1e6))
    
04.01.2019 / 17:53