Ответ 1
В комментариях к этому вопросу обсуждается, что во многих случаях вы можете найти альтернативу в dplyr или связанных пакетах, которые избегают использования do
, и примеры в вопросе относятся к этому типу; однако, чтобы ответить на вопрос напрямую, а не на альтернативы:
Различия между использованием do и не использованием
В контексте кадров данных ключевыми различиями между использованием do
и без использования do
являются:
-
Автоматическая установка точки. Код внутри
do
не будет автоматически вставлен в первый аргумент. Например, вместо кодаdo(summarise(Mean_2014 = mean(Y2014)))
в вопросе нужно было бы написатьdo(summarise(., Mean_2014 = mean(Y2014)))
с точкой, поскольку точка не будет автоматически вставлена. Это является следствием того, чтоdo
является правой частью функции%>%
, а неsummarize
. Хотя это важно понимать так, чтобы мы вставляли точку, когда это было необходимо, если целью было просто избежать автоматической вставки точки в первый аргумент, мы могли бы попеременно использовать скобки для получения этого эффекта:whatever %>% { myfun(arg1, arg2) }
также не будет автоматически вставлять точку в качестве первый аргумент вызоваmyfun
. -
respecting group_by Только функции, специально написанные для соблюдения
group_by
, сделают это. Здесь есть два вопроса. (1) Только функции, специально написанные для оценкиgroup_by
, будут выполняться один раз для каждой группы.mutate
,summarize
иdo
являются примерами функций, которые запускаются один раз для каждой группы (есть и другие). (2) Даже если функция запускается один раз для каждой группы, возникает вопрос о том, как обрабатывается точка. Мы фокусируемся на двух случаях (не полный список): (i) еслиdo
не используется, то, если точка используется в вызове функции в выражении для аргумента, она будет ссылаться на весь вход, игнорируяgroup_by
. Предположительно это является следствием правил замены магритт-точек и ничего не знает оgroup_by
. С другой стороны, (ii) в пределахdo
точка всегда относится к строкам текущей группы. Например, сравните вывод этих двух и обратите внимание, что точка относится к 3 строкам в первом случае, когда используетсяdo
, и все 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
В приведенном выше коде создается 2 строки для каждой из 3 групп, дающих 6 строк. Если бы мы опустили do
, тогда он проигнорировал бы group_by
и произвел только две строки с точкой, считающейся целыми 9 строками ввода, а не только каждой группой за раз. (В этом конкретном случае dplyr предоставляет свою собственную альтернативу 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
, поэтому нет необходимости обертывать его в 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