使用%>%管道和点(。)表示法

时间:2022-12-22 22:30:07

When using map on a nested data_frame, I do not understand why the latter two version give an error, how should I use the dot (.)?

在嵌套的data_frame上使用map时,我不明白为什么后两个版本会出错,我应该如何使用点(。)?

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)

1 个解决方案

#1


9  

The problem isn't map, but rather how the %>% pipe deals with the .. Consider the following examples (remember that / is a two argument function in R):

问题不是map,而是%>%pipe如何处理..请考虑以下示例(请记住/是R中的两个参数函数):

Simple piping:

1 %>% `/`(2)

Is equivalent to `/`(1, 2) or 1 / 2 and gives 0.5.

相当于`/`(1,2)或1/2,并给出0.5。

Simple . use:

1 %>% `/`(2, .)

Is equivalent to `/`(2, 1) or 2 / 1 and gives 2.

相当于`/`(2,1)或2/1并给出2。

You can see that 1 is no longer used as the first argument, but only as the second.

您可以看到1不再用作第一个参数,而只是作为第二个参数。

Other . use:

This doesn't work however, when subsetting the .:

但是,在对。进行子集化时,这不起作用:

list(a = 1) %>% `/`(.$a, 2)
Error in `/`(., .$a, 2) : operator needs one or two arguments

We can see that . got injected twice, as the first argument and subsetted in the second argument. An expression like .$a is sometimes referred to as a nested function call (the $ function is used inside the / function, in this case).

我们可以看到。被注入两次,作为第一个参数并在第二个参数中进行了子集化。像。$ a这样的表达式有时被称为嵌套函数调用(在这种情况下,$函数在/ function中使用)。

We use braces to avoid first argument injection:

我们使用大括号来避免第一次参数注入:

list(a = 1) %>% { `/`(.$a, 2) }

Gives 0.5 again.

再次给出0.5。

Actual problem:

You are actually calling map(df, df$data, min), not map(df$data, min).

你实际上是在调用map(df,df $ data,min),而不是map(df $ data,min)。

Solution:

Use braces:

使用大括号:

df %>% { map(.$data, min) }

Also see the header Using the dot for secondary purposes in ?magrittr::`%>%` which reads:

另请参阅标题在?magrittr ::`%>%`中使用点作为次要用途,其中包含:

In particular, if the placeholder is only used in a nested function call, lhs will also be placed as the first argument! The reason for this is that in most use-cases this produces the most readable code. For example, iris %>% subset(1:nrow(.) %% 2 == 0) is equivalent to iris %>% subset(., 1:nrow(.) %% 2 == 0) but slightly more compact. It is possible to overrule this behavior by enclosing the rhs in braces. For example, 1:10 %>% {c(min(.), max(.))} is equivalent to c(min(1:10), max(1:10)).

特别是,如果占位符仅用于嵌套函数调用,则lhs也将作为第一个参数放置!这样做的原因是,在大多数用例中,这会产生最易读的代码。例如,iris%>%subset(1:nrow(。)%% 2 == 0)等同于iris%>%subset(。,1:nrow(。)%% 2 == 0)但稍微更紧凑。通过将rhs括在大括号中可以否决这种行为。例如,1:10%>%{c(min(。),max(。))}等于c(min(1:10),max(1:10))。

#1


9  

The problem isn't map, but rather how the %>% pipe deals with the .. Consider the following examples (remember that / is a two argument function in R):

问题不是map,而是%>%pipe如何处理..请考虑以下示例(请记住/是R中的两个参数函数):

Simple piping:

1 %>% `/`(2)

Is equivalent to `/`(1, 2) or 1 / 2 and gives 0.5.

相当于`/`(1,2)或1/2,并给出0.5。

Simple . use:

1 %>% `/`(2, .)

Is equivalent to `/`(2, 1) or 2 / 1 and gives 2.

相当于`/`(2,1)或2/1并给出2。

You can see that 1 is no longer used as the first argument, but only as the second.

您可以看到1不再用作第一个参数,而只是作为第二个参数。

Other . use:

This doesn't work however, when subsetting the .:

但是,在对。进行子集化时,这不起作用:

list(a = 1) %>% `/`(.$a, 2)
Error in `/`(., .$a, 2) : operator needs one or two arguments

We can see that . got injected twice, as the first argument and subsetted in the second argument. An expression like .$a is sometimes referred to as a nested function call (the $ function is used inside the / function, in this case).

我们可以看到。被注入两次,作为第一个参数并在第二个参数中进行了子集化。像。$ a这样的表达式有时被称为嵌套函数调用(在这种情况下,$函数在/ function中使用)。

We use braces to avoid first argument injection:

我们使用大括号来避免第一次参数注入:

list(a = 1) %>% { `/`(.$a, 2) }

Gives 0.5 again.

再次给出0.5。

Actual problem:

You are actually calling map(df, df$data, min), not map(df$data, min).

你实际上是在调用map(df,df $ data,min),而不是map(df $ data,min)。

Solution:

Use braces:

使用大括号:

df %>% { map(.$data, min) }

Also see the header Using the dot for secondary purposes in ?magrittr::`%>%` which reads:

另请参阅标题在?magrittr ::`%>%`中使用点作为次要用途,其中包含:

In particular, if the placeholder is only used in a nested function call, lhs will also be placed as the first argument! The reason for this is that in most use-cases this produces the most readable code. For example, iris %>% subset(1:nrow(.) %% 2 == 0) is equivalent to iris %>% subset(., 1:nrow(.) %% 2 == 0) but slightly more compact. It is possible to overrule this behavior by enclosing the rhs in braces. For example, 1:10 %>% {c(min(.), max(.))} is equivalent to c(min(1:10), max(1:10)).

特别是,如果占位符仅用于嵌套函数调用,则lhs也将作为第一个参数放置!这样做的原因是,在大多数用例中,这会产生最易读的代码。例如,iris%>%subset(1:nrow(。)%% 2 == 0)等同于iris%>%subset(。,1:nrow(。)%% 2 == 0)但稍微更紧凑。通过将rhs括在大括号中可以否决这种行为。例如,1:10%>%{c(min(。),max(。))}等于c(min(1:10),max(1:10))。