何时在dplyr中使用“Do”功能

时间:2018-01-10 08:05:36

标签: r dplyr

我了解到,当您想要将函数应用于每个组时,会使用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>

1 个答案:

答案 0 :(得分:12)

该问题下的评论讨论了在许多情况下,您可以在dplyr或相关软件包中找到一个替代方法,避免使用do,并且问题中的示例属于那种类型;然而,要直接回答这个问题而不是通过替代方案:

使用do和不使用它之间的差异

在数据框架的上下文中,使用do和不使用do之间的主要区别是:

  1. 没有自动插入点 do中的代码不会自动插入第一个参数中的点。例如,代替问题中的do(summarise(Mean_2014 = mean(Y2014)))代码,必须用点写do(summarise(., Mean_2014 = mean(Y2014))),因为点不会自动插入。这是do%>%而不是summarize的右手边功能的结果。虽然这很重要,但是如果目的只是为了避免在第一个参数中自动插入点,我们可以在需要时插入点,我们可以交替使用括号括号来实现这个效果:whatever %>% { myfun(arg1, arg2) } not 自动插入点作为myfun调用的第一个参数。

  2. 尊重group_by 只有专门针对group_by编写的功能才会这样做。这里有两个问题。 (1)对于每个组,只有专门针对group_by编写的函数才会运行一次。 mutatesummarizedo是每个群组运行一次​​的功能示例(还有其他功能)。 (2)即使每个组运行一次​​函数,也存在如何处理点的问题。我们关注两个案例(不是完整的列表):( i)如果没有使用do那么如果在表达式中的函数调用中使用点到参数,它将引用忽略{{1的整个输入}}。据推测,这是magrittr的点替换规则的结果,并且它对group_by一无所知。另一方面(ii)group_by点内的总是指当前组的行。例如,比较这两者的输出并注意,在第一种使用do的情况下,dot指的是3行,而在第二种情况下,不是所有6行。尽管do尊重summarize,但每个群组都会运行一次。

    group_by
  3. 有关详细信息,请参阅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
相关问题