Я пытаюсь перенести свое понимание plyr в dplyr, но не могу понять, как группировать по нескольким столбцам.
# make data with weird column names that can't be hard coded
data = data.frame(
asihckhdoydkhxiydfgfTgdsx = sample(LETTERS[1:3], 100, replace=TRUE),
a30mvxigxkghc5cdsvxvyv0ja = sample(LETTERS[1:3], 100, replace=TRUE),
value = rnorm(100)
)
# get the columns we want to average within
columns = names(data)[-3]
# plyr - works
ddply(data, columns, summarize, value=mean(value))
# dplyr - raises error
data %.%
group_by(columns) %.%
summarise(Value = mean(value))
#> Error in eval(expr, envir, enclos) : index out of bounds
Чего мне не хватает, чтобы перевести пример plyr в синтаксис dplyr-esque?
Редактировать 2017 : Dplyr был обновлен, поэтому доступно более простое решение. Смотрите текущий выбранный ответ.
group_by_
теперь объяснил вvignette("nse")
.dots
. Вот решение, адаптированное из ответа @hadley ниже:df %>% group_by_(.dots=list(quote(asihckhdoydk), quote(a30mvxigxkgh))) %>% summarise(n = n())
Ответы:
Поскольку этот вопрос был опубликован, dplyr добавил версии с определенными областями
group_by
( документация здесь ). Это позволяет вам использовать те же функции, которые вы использовали быselect
, например:Вывод вашего примера вопроса, как и ожидалось (см. Сравнение с plyr выше и вывод ниже):
Обратите внимание, что, поскольку
dplyr::summarize
за один раз удаляется только один слой группировки, в результирующем тибле все еще происходит группировка (которая может иногда застать людей врасплох). Если вы хотите быть абсолютно в безопасности от неожиданного поведения группирования, вы всегда можете добавить%>% ungroup
в свой конвейер после подведения итогов.источник
0.7.0
того, чтобы сделать систему цитирования-цитаты доступной с несколькими столбцами?.dots
аргументыgroup_by()
как таковой:data %>% group_by(.dots = columns) %>% summarize(value = mean(value))
.one_of()
сделать что-нибудь здесь? Я думаю, что это избыточно в этом контексте, так как выражение обернуто в вызовеvars()
.one_of()
в этом контексте призыв к избыточностиselect
синтаксис, увидеть новуюacross
функцию: dplyr.tidyverse.org/reference/across.html В вашем случае, это будет выглядеть примерно такsummarize(across(all_of(c(''value_A", "value_B")), mean))
Чтобы полностью написать код, вот обновление ответа Хэдли с новым синтаксисом:
вывод:
источник
asihckhdoydk
...dots <- lapply(names(df)[-3], function(x) as.symbol(x))
.dots
.dots=
была решающим шагом. если кто-то знает, почему это требуется приgroup_by
вызове, можете ли вы отредактировать этот ответ? сейчас это немного непостижимо.vignette("nse")
указывает, что есть три способа цитирования, которые являются приемлемыми: формула, цитата и символ. Если вы не беспокоитесь о том, из какой среды он будет тянуться, вы, вероятно, можете сойти с рукgroup_by_(.dots=grp_cols)
Поддержка этого в dplyr в настоящее время довольно слабая, в конце концов я думаю, что синтаксис будет примерно таким:
Но этого, вероятно, не будет некоторое время (потому что мне нужно продумать все последствия).
В то же время, вы можете использовать
regroup()
, который принимает список символов:Если у вас есть символьный вектор имен столбцов, вы можете преобразовать их в правильную структуру с помощью
lapply()
иas.symbol()
:источник
as.symbol
решает это. Спасибо! В случае, если это помогает в разработке: этот сценарий действительно распространен для меня. Агрегируйте числовой результат по каждой комбинации других переменных.regroup
также не рекомендуется (по крайней мере, начиная с версии 0.4.3).Строковая спецификация столбцов в
dplyr
теперь поддерживается через вариантыdplyr
функций с именами, заканчивающимися подчеркиванием. Например, соответствующаяgroup_by
функции естьgroup_by_
функция, которая может принимать строковые аргументы. Эта виньетка подробно описывает синтаксис этих функций.Следующий фрагмент кода четко решает проблему, которую изначально поставил @sharoz (обратите внимание на необходимость выписать
.dots
аргумент):(Обратите внимание, что dplyr теперь использует
%>%
оператор и%.%
не рекомендуется).источник
Пока dplyr не получит полную поддержку строковых аргументов, возможно, эта суть полезна:
https://gist.github.com/skranz/9681509
Он содержит множество функций-оболочек, таких как s_group_by, s_mutate, s_filter и т. Д., Которые используют строковые аргументы. Вы можете смешивать их с обычными функциями dplyr. Например
источник
Это работает, если вы передаете ему объекты (ну, вы не, но ...), а не как символьный вектор:
где
df
была вашаdata
.?group_by
говорит:который я интерпретирую, чтобы обозначать не символьные версии имен, а то, как вы бы на них ссылались
foo$bar
;bar
здесь не цитируется Или как вы бы ссылаться на переменные в формулеfoo ~ bar
.@Arun также упоминает, что вы можете сделать:
Но вы не можете передать то, что не оценено , не является именем переменной в объекте данных.
Я предполагаю, что это связано с внутренними методами, которые Хэдли использует для поиска вещей, которые вы передаете через
...
аргумент.источник
источник
Один (крошечный) случай, который отсутствует в ответах здесь, который я хотел бы сделать явным, - это когда переменные для группировки динамически генерируются в середине потока в конвейере:
Это в основном показывает, как использовать
grep
в сочетании сgroup_by_(.dots = ...)
для достижения этой цели.источник
Общий пример использования
.dots
аргумента в качестве входного векторного символа дляdplyr::group_by
функции:Или без жестко закодированного имени для группирующей переменной (согласно запросу OP):
На примере ОП:
См. Также виньетка dplyr по программированию, которая объясняет местоимения, квази-цитаты, фразы и тидевал.
источник