Группировать по нескольким столбцам в dplyr, используя ввод векторной строки

Я пытаюсь передать свое понимание 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 обновлен, поэтому доступно более простое решение. См. Текущий выбранный ответ.

Поскольку этот вопрос был отправлен, dplyr добавила расширенные версии group_by ( документация здесь ). Это позволяет использовать те же функции, которые вы бы использовали при select , например:

 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] library(dplyr) df1 <- data %>% group_by_at(vars(one_of(columns))) %>% summarize(Value = mean(value)) #compare plyr for reference df2 <- plyr::ddply(data, columns, plyr::summarize, value=mean(value)) table(df1 == df2, useNA = 'ifany') ## TRUE ## 27 

Вывод из вашего примерного вопроса выглядит так, как ожидалось (см. Сравнение с выше и выше ниже):

 # A tibble: 9 x 3 # Groups: asihckhdoydkhxiydfgfTgdsx [?] asihckhdoydkhxiydfgfTgdsx a30mvxigxkghc5cdsvxvyv0ja Value    1 AA 0.04095002 2 AB 0.24943935 3 AC -0.25783892 4 BA 0.15161805 5 BB 0.27189974 6 BC 0.20858897 7 CA 0.19502221 8 CB 0.56837548 9 CC -0.22682998 

Обратите внимание, что поскольку dplyr::summarize только полосы от одного слоя группировки за раз, у вас все еще есть какая-то группировка в итоговой форме (которая может когда-нибудь улавливать людей на удивление позже по линии). Если вы хотите быть абсолютно безопасным от неожиданного поведения группировки, вы всегда можете добавить %>% ungroup в свой конвейер после суммирования.

Чтобы полностью написать код, вот обновление ответа Хэдли с новым синтаксисом:

 library(dplyr) df <- data.frame( asihckhdoydk = sample(LETTERS[1:3], 100, replace=TRUE), a30mvxigxkgh = sample(LETTERS[1:3], 100, replace=TRUE), value = rnorm(100) ) # Columns you want to group by grp_cols <- names(df)[-3] # Convert character vector to list of symbols dots <- lapply(grp_cols, as.symbol) # Perform frequency counts df %>% group_by_(.dots=dots) %>% summarise(n = n()) 

вывод:

 Source: local data frame [9 x 3] Groups: asihckhdoydk asihckhdoydk a30mvxigxkgh n 1 AA 10 2 AB 10 3 AC 13 4 BA 14 5 BB 10 6 BC 12 7 CA 9 8 CB 12 9 CC 10 

Поддержка этого в dplyr в настоящее время довольно слабая, в конце концов я думаю, что синтаксис будет примерно таким:

 df %.% group_by(.groups = c("asdfgfTgdsx", "asdfk30v0ja")) 

Но этого, вероятно, не будет на какое-то время (потому что мне нужно продумать все последствия).

Тем временем вы можете использовать команду regroup() , которая принимает список символов:

 library(dplyr) df <- data.frame( asihckhdoydk = sample(LETTERS[1:3], 100, replace=TRUE), a30mvxigxkgh = sample(LETTERS[1:3], 100, replace=TRUE), value = rnorm(100) ) df %.% regroup(list(quote(asihckhdoydk), quote(a30mvxigxkgh))) %.% summarise(n = n()) 

Если у вас есть вектор символов имен столбцов, вы можете преобразовать их в нужную структуру с помощью lapply() и as.symbol() :

 vars <- setdiff(names(df), "value") vars2 <- lapply(vars, as.symbol) df %.% regroup(vars2) %.% summarise(n = n()) 

Строковая спецификация столбцов в dplyr теперь поддерживается вариантами функций dplyr с именами, заканчивающимися в подчеркивании. Например, для функции group_by существует функция group_by_ которая может принимать строковые аргументы. Эта виньетка подробно описывает синтаксис этих функций.

Следующий fragment полностью решает проблему, которую первоначально поставил @sharoz (обратите внимание на необходимость записи аргумента .dots ):

 # Given data and columns from the OP data %>% group_by_(.dots = columns) %>% summarise(Value = mean(value)) 

(Обратите внимание, что dplyr теперь использует оператор %>% , а %.% Устарел).

До тех пор, пока dplyr не будет полностью поддерживать строковые аргументы, возможно, этот смысл полезен:

https://gist.github.com/skranz/9681509

Он содержит множество функций-оберток, таких как s_group_by, s_mutate, s_filter и т. Д., Которые используют строковые аргументы. Вы можете смешивать их с обычными функциями dplyr. Например

 cols = c("cyl","gear") mtcars %.% s_group_by(cols) %.% s_summarise("avdisp=mean(disp), max(disp)") %.% arrange(avdisp) 

Он работает, если вы передадите ему объекты (ну, вы не, но …), а не как вектор символов:

 df %.% group_by(asdfgfTgdsx, asdfk30v0ja) %.% summarise(Value = mean(value)) > df %.% + group_by(asdfgfTgdsx, asdfk30v0ja) %.% + summarise(Value = mean(value)) Source: local data frame [9 x 3] Groups: asdfgfTgdsx asdfgfTgdsx asdfk30v0ja Value 1 AC 0.046538002 2 CB -0.286359899 3 BA -0.305159419 4 CA -0.004741504 5 BB 0.520126476 6 CC 0.086805492 7 BC -0.052613078 8 AA 0.368410146 9 AB 0.088462212 

где df – ваши data .

?group_by говорит:

  ...: variables to group by. All tbls accept variable names, some will also accept functons of variables. Duplicated groups will be silently dropped. 

которые я интерпретирую как означающие не имена символов, но как вы относитесь к ним в foo$bar ; bar здесь не цитируется. Или как вы относитесь к переменным в формуле: foo ~ bar .

@Arun также упоминает, что вы можете сделать:

 df %.% group_by("asdfgfTgdsx", "asdfk30v0ja") %.% summarise(Value = mean(value)) 

Но вы не можете передать что-то, что не оценено, это не имя переменной в объекте данных.

Я предполагаю, что это связано с внутренними методами, которые использует Хэдли для поиска вещей, которые вы проходите через аргумент ...

 data = data.frame( my.a = sample(LETTERS[1:3], 100, replace=TRUE), my.b = sample(LETTERS[1:3], 100, replace=TRUE), value = rnorm(100) ) group_by(data,newcol=paste(my.a,my.b,sep="_")) %>% summarise(Value=mean(value)) 

Один (крошечный) случай, отсутствующий в ответах здесь, который я хотел бы сделать явным, – это когда переменные, которые группируются, генерируются динамически в streamе в конвейере:

 library(wakefield) df_foo = r_series(rnorm, 10, 1000) df_foo %>% # 1. create quantized versions of base variables mutate_each( funs(Quantized = . > 0) ) %>% # 2. group_by the indicator variables group_by_( .dots = grep("Quantized", names(.), value = TRUE) ) %>% # 3. summarize the base variables summarize_each( funs(sum(., na.rm = TRUE)), contains("X_") ) 

Это в основном показывает, как использовать grep в сочетании с group_by_(.dots = ...) для достижения этого.

  • Запустите Sweave или knitr с объектами из существующей сессии R
  • Таблица взаимодействий - случай с домашними животными и домами
  • Участок с осью 2 y, одна ось y слева и другая ось y справа
  • R.exe, Rcmd.exe, Rscript.exe и Rterm.exe: какая разница?
  • Сравните два data.frames, чтобы найти строки в data.frame 1, которых нет в data.frame 2
  • R и системные вызовы
  • Удалить столбцы с нулевыми значениями из фрейма данных
  • Можете ли вы указать разные геометрии для разных граней в ggplot?
  • Вложенный оператор ifelse
  • чтение текстового файла в строке R
  • Согласование нескольких шаблонов
  • Interesting Posts

    Суммирование нескольких ячеек, соответствующих критериям столбца и столбца?

    Linux: интерпретируется на чтение (ala php) для локальных файлов

    Можно ли общаться с другими пользователями WiFi в доме?

    Как сделать радарную диаграмму пирога

    В чем разница между списками параметров и несколькими параметрами в списке в Scala?

    Вызов форм из диалоговых окон

    OpenERP 7 Как предоставить пользователям доступ к настраиваемому модулю в OpenERP 7?

    Как заострить изображение в OpenCV?

    .NET Проблемы с памятью загружаются ~ 40 изображений, память не регенерирована, потенциально из-за fragmentации LOH

    Как я могу получить высоту и ширину панели навигации Android программно?

    Какой алгоритм может вычислить набор мощности данного набора?

    Простая анимация с использованием C # / Windows Forms

    Будет ли больше RAM или больше CPU лучше для NAS (сетевой диск)?

    Можно ли преобразовать существующую установку Firefox в ESR без переустановки?

    Почему C ++ 11 не поддерживает назначенные списки инициализаторов как C99?

    Давайте будем гением компьютера.