Usando la notación %>% barra vertical y punto (.)
Cuando lo uso map
en un data_frame anidado, no entiendo por qué las dos últimas versiones dan un error, ¿cómo debo usar el punto ( .
)?
library(tidyverse)
# dummy data
df <- tibble(id = rep(1:10, each = 10),
val = runif(100))
df <- nest(df, -id)
# works as expected
map(df$data, min)
df %>% .$data %>% map(., min)
# gives an error
df %>% map(.$data, min)
# Error: Don't know how to index with object of type list at level 1
df %>% map(data, min)
El problema no es map
, sino más bien cómo %>%
maneja la tubería el .
. Considere los siguientes ejemplos (recuerde que /
es una función de dos argumentos en R):
Tuberías sencillas:
1 %>% `/`(2)
Equivale a `/`(1, 2)
o 1 / 2
y da 0.5
.
También es equivalente a 1 %>% `/`(., 2)
.
Uso sencillo .
:
1 %>% `/`(2, .)
Equivale a `/`(2, 1)
o 2 / 1
y da 2
.
Puedes ver que 1
ya no se utiliza como primer argumento, sino sólo como segundo.
Otro .
uso:
Sin embargo, esto no funciona cuando se subconjunto .
:
list(a = 1) %>% `/`(.$a, 2)
Error in `/`(., .$a, 2) : operator needs one or two arguments
Podemos ver que .
se inyectó dos veces, como primer argumento y como subconjunto en el segundo argumento. Una expresión como .$a
a veces se denomina llamada a función anidada (en este caso, la $
función se usa dentro de la /
función).
Usamos llaves para evitar la inyección del primer argumento:
list(a = 1) %>% { `/`(.$a, 2) }
Da 0,5 de nuevo.
Problema real:
En realidad estás llamando map(df, df$data, min)
, no map(df$data, min)
.
Solución:
Utilice aparatos ortopédicos:
df %>% { map(.$data, min) }
Véase también el encabezado Uso del punto con fines secundarios en ?magrittr::`%>%`
el que se lee:
En particular, si el marcador de posición solo se usa en una llamada a función anidada, ¡lhs también se colocará como primer argumento! La razón de esto es que en la mayoría de los casos de uso esto produce el código más legible. Por ejemplo,
iris %>% subset(1:nrow(.) %% 2 == 0)
es equivalenteiris %>% subset(., 1:nrow(.) %% 2 == 0)
pero ligeramente más compacto. Es posible anular este comportamiento encerrando el derecho entre llaves. Por ejemplo,1:10 %>% {c(min(.), max(.))}
equivale ac(min(1:10), max(1:10))
.