我了解到,当您想要将函数应用于每个组时,会使用Do
函数。
例如,如果我想从变量Index
的“A”,“C”和“I”类别中拉出前2行,则可以使用以下语法。
t <- mydata %>% filter(Index %in% c("A", "C", "I")) %>% group_by(Index) %>% do(head(.,2))
据我所知,按索引分组后,do
函数用于计算每个组的头(。,2)。
但是,在某些情况下,根本不使用do
。例如,要计算按变量Y2014
分组的变量Index
的平均值,我认为应该使用以下代码。
t <- mydata %>% group_by(Index) %>% do(summarise(Mean_2014 = mean(Y2014)))
但是,上面的语法会返回错误
Error in mean(Y2014) : object 'Y2014' not found
但是如果我从语法中删除do
,它会返回我想要的内容。
t <- mydata %>% group_by(Index) %>% summarise(Mean_2014 = mean(Y2014))
我对dplyr中do
函数的使用感到困惑。这对我来说似乎不一致。我应该何时使用而不使用do
功能?为什么我应该在第一种情况下使用do
而在第二种情况下不使用?{/ p>
答案 0 :(得分:12)
该问题下的评论讨论了在许多情况下,您可以在dplyr或相关软件包中找到一个替代方法,避免使用do
,并且问题中的示例属于那种类型;然而,要直接回答这个问题而不是通过替代方案:
在数据框架的上下文中,使用do
和不使用do
之间的主要区别是:
没有自动插入点 do
中的代码不会自动插入第一个参数中的点。例如,代替问题中的do(summarise(Mean_2014 = mean(Y2014)))
代码,必须用点写do(summarise(., Mean_2014 = mean(Y2014)))
,因为点不会自动插入。这是do
是%>%
而不是summarize
的右手边功能的结果。虽然这很重要,但是如果目的只是为了避免在第一个参数中自动插入点,我们可以在需要时插入点,我们可以交替使用括号括号来实现这个效果:whatever %>% { myfun(arg1, arg2) }
也 not 自动插入点作为myfun
调用的第一个参数。
尊重group_by 只有专门针对group_by
编写的功能才会这样做。这里有两个问题。 (1)对于每个组,只有专门针对group_by
编写的函数才会运行一次。 mutate
,summarize
和do
是每个群组运行一次的功能示例(还有其他功能)。 (2)即使每个组运行一次函数,也存在如何处理点的问题。我们关注两个案例(不是完整的列表):( i)如果没有使用do
那么如果在表达式中的函数调用中使用点到参数,它将引用忽略{{1的整个输入}}。据推测,这是magrittr的点替换规则的结果,并且它对group_by
一无所知。另一方面(ii)group_by
点内的总是指当前组的行。例如,比较这两者的输出并注意,在第一种使用do
的情况下,dot指的是3行,而在第二种情况下,不是所有6行。尽管do
尊重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
上面的代码为3组中的每一组产生2行,给出6行。如果我们省略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
那么它将忽略do
并且只生成两行,其中dot被视为整个9行输入,而不是一次只有每组。 (在这种特殊情况下,dplyr为group_by
提供了自己的替代方法,避免了这些问题,但为了说明我们坚持问题代码的一般观点。)
问题中的以下代码会产生错误,因为点插入不是在head
内完成的,所以应该是总结的第一个参数,即数据框输入,是:
do
如果我们删除上述代码中的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
中{1}}。
do