问题下的 cmets 讨论了在许多情况下,您可以在 dplyr 或相关软件包中找到避免使用 do 的替代方案,并且问题中的示例属于这种情况;但是,直接回答这个问题而不是通过替代方法:
使用do和不使用的区别
在数据帧的上下文中,使用do 和不使用do 之间的主要区别是:
不自动插入点do 中的代码不会将点自动插入到第一个参数中。例如,不是问题中的do(summarise(Mean_2014 = mean(Y2014))) 代码,而是必须用点编写do(summarise(., Mean_2014 = mean(Y2014))),因为点不会自动插入。这是do 是%>% 而不是summarize 的右侧函数的结果。虽然理解这一点很重要,以便我们在需要时插入点,如果目的只是为了避免将点自动插入第一个参数,我们可以交替使用大括号来获得这种效果:whatever %>% { myfun(arg1, arg2) } 也 not em> 自动插入点作为myfun 调用的第一个参数。
-
尊重 group_by 只有专门为尊重group_by 而编写的函数才会这样做。这里有两个问题。 (1) 只有专门为尊重group_by 而编写的函数才会为每个组运行一次。 mutate、summarize 和 do 是每组运行一次的函数示例(还有其他函数)。 (2) 即使函数对每个组运行一次,也存在如何处理点的问题。我们关注两种情况(不是完整的列表):(i)如果do 没有被使用,那么如果在一个函数调用中对一个参数的表达式使用点,它将引用整个输入而忽略group_by。大概这是 magrittr 的点替换规则的结果,它对group_by 一无所知。另一方面 (ii) 在do dot 内总是指当前组的行。例如,比较这两者的输出并注意在第一种情况下使用 do 时 dot 表示 3 行,而在第二种情况下没有使用 6 行。尽管summarize 尊重group_by,因为它每组运行一次。
BOD$g <- c(1, 1, 1, 2, 2, 2)
BOD %>% group_by(g) %>% do(summarize(., nr = nrow(.)))
## # A tibble: 2 x 2
## # Groups: g [2]
## g nr
## <dbl> <int>
## 1 1.00 3
## 2 2.00 3
BOD %>% group_by(g) %>% summarize(nr = nrow(.))
## # A tibble: 2 x 2
## g nr
## <dbl> <int>
## 1 1.00 6
## 2 2.00 6
更多信息请参见?do。
问题代码
现在我们查看问题中的代码。由于mydata 从未在问题中定义,我们使用下面的第一行代码来定义它以方便具体示例。
mydata <- data.frame(Index = rep(c("A", "C", "I"), each = 3), Y2014 = 1)
mydata %>%
filter(Index %in% c("A", "C", "I")) %>%
group_by(Index) %>%
do(head(., 2))
## # A tibble: 6 x 2
## # Groups: Index [3]
## Index Y2014
## <fctr> <dbl>
## 1 A 1.00
## 2 A 1.00
## 3 C 1.00
## 4 C 1.00
## 5 I 1.00
## 6 I 1.00
上面的代码为 3 组中的每组生成 2 行,共 6 行。如果我们省略了do,那么它将忽略group_by,只生成两行,点被视为整个9行输入,而不是一次只生成每一组。 (在这种特殊情况下,dplyr 提供了自己的 head 替代方案,可以避免这些问题,但为了说明一般观点,我们坚持问题中的代码。)
问题中的以下代码会产生错误,因为点插入未在 do 内完成,因此缺少 summarise 的第一个参数,即数据框输入:
mydata %>%
group_by(Index) %>%
do(summarise(Mean_2014 = mean(Y2014)))
## Error in mean(Y2014) : object 'Y2014' not found
如果我们删除上面代码中的do,就像问题中的最后一行代码一样,那么它可以工作,因为执行了点插入。或者,如果我们添加点do(summarise(., Mean_2014 = mean(Y2014))),它也可以工作,尽管do 在这种情况下看起来真的是多余的,因为summarize 已经尊重group_by,所以没有必要将它包装在do 中。
mydata %>%
group_by(Index) %>%
summarise(Mean_2014 = mean(Y2014))
## # A tibble: 3 x 2
## Index Mean_2014
## <fctr> <dbl>
## 1 A 1.00
## 2 C 1.00
## 3 I 1.00