Группировать по нескольким столбцам в 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 = ...) для достижения этого.

  • Невозможно выполнить цикл с пакетом листов R для создания нескольких карт
  • Точное хранение больших целых чисел
  • Ошибка в R: (пакет, который доступен только в исходной форме и может потребоваться компиляция C / C ++ / Fortran)
  • Толщина границы контрольной точки в ggplot
  • Создание участка с разбивкой по областям с использованием ggplot2
  • Как вы нарисуете линию в многозначной среде в R?
  • Как организовать большие программы R?
  • Как увеличить размер шрифта на графике в R?
  • Есть ли функция R, чтобы избежать строки для символов регулярных выражений
  • Как создать ряд наиболее отличительных цветов в R?
  • Комбинировать базовую графику и графику ggplot в окне фигуры R
  • Interesting Posts

    Сообщение для facebook wall from android fb sdk всегда ошибка

    * .h или * .hpp для определения classов

    Размер экрана для Android с одинаковой плотностью

    Суперпростой пример наблюдателя C # / наблюдаемого с делегатами

    Случайно переписан неправильный диск с dd, как восстановить?

    В MvvmCross, как мне выполнять пользовательские свойства привязки

    Выполнить серию команд на разных вкладках в conemu

    Стеганографическое программное обеспечение

    Автоматическая блокировка экрана для любого пользователя после определенного периода бездействия в Windows 7

    Как правильно выразить JPQL «join fetch» ​​с предложением «where» как JPA 2 CriteriaQuery?

    ANSI – UTF-8 в Notepad ++

    Внедрение переменной javascript перед скриптом содержимого

    Получение последнего дня месяца в заданной строковой дате

    Windows 7 говорит, что 8,6-гигабайтный файл не поместится в 14,7 ГБ пространства?

    Кнопки диалогового окна не работают в Eclipse на Ubuntu 9.10

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