Подтвердить что ты не робот

Используя 'mutate_', чтобы суммировать кучу столбцов по ряду строк

В этом сообщении в блоге Пол Хиемстра показывает, как суммировать два столбца с помощью dplyr::mutate_. Копирование/вставка соответствующих частей:

library(lazyeval)
f = function(col1, col2, new_col_name) {
    mutate_call = lazyeval::interp(~ a + b, a = as.name(col1), b = as.name(col2))
    mtcars %>% mutate_(.dots = setNames(list(mutate_call), new_col_name))
}

позволяет выполнить следующее:

head(f('wt', 'mpg', 'hahaaa'))

Отлично!

Я рассмотрел вопрос (см. комментарии) о том, как можно распространить это на 100 столбцов, так как было не совсем ясно (мне), как это можно сделать, не набирая все имена, используя выше способ. Пол был достаточно любезен, чтобы побаловать меня и предоставил этот ответ (спасибо!):

# data
df = data.frame(matrix(1:100, 10, 10))
names(df) = LETTERS[1:10]

# answer
sum_all_rows = function(list_of_cols) {
  summarise_calls = sapply(list_of_cols, function(col) {
    lazyeval::interp(~col_name, col_name = as.name(col))
  })
  df %>% select_(.dots = summarise_calls) %>% mutate(ans1 = rowSums(.))
}
sum_all_rows(LETTERS[sample(1:10, 5)])

Я бы хотел улучшить этот ответ по этим вопросам:

  • Остальные столбцы исчезли. Я хотел бы сохранить их.

  • Он использует rowSums(), который должен принуждать data.frame к матрице, которую я бы хотел избежать.

    Также я не уверен, что рекомендуется использовать . в пределах do() глаголов? Поскольку . внутри mutate(), похоже, не подходит для этих строк при использовании с group_by().

  • И самое главное, как я могу сделать то же самое с помощью mutate_() вместо mutate()?

Я нашел этот ответ, который касается пункта 1, но, к сожалению, оба ответа dplyr используют rowSums() вместе с mutate().


PS: Я просто прочитал комментарий Хэдли под этим ответом. IIUC, "изменить форму на длинную форму + группу на + сумма + изменить на широкую форму" является рекомендуемым способом dplyr для этих типов операций?

4b9b3361

Ответ 1

Здесь другой подход:

library(dplyr); library(lazyeval)
f <- function(df, list_of_cols, new_col) {
  df %>% 
    mutate_(.dots = ~Reduce(`+`, .[list_of_cols])) %>% 
    setNames(c(names(df), new_col))
}

head(f(mtcars, c("mpg", "cyl"), "x"))
#   mpg cyl disp  hp drat    wt  qsec vs am gear carb    x
#1 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4 27.0
#2 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4 27.0
#3 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1 26.8
#4 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1 27.4
#5 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2 26.7
#6 18.1   6  225 105 2.76 3.460 20.22  1  0    3    1 24.1

Относительно ваших баллов:

  • Остальные столбцы сохраняются
  • Он не использует rowSums
  • Здесь вы конкретно запрашиваете операцию с использованием строки, поэтому я не уверен (пока), как group_by может нанести ущерб при использовании . внутри mutate/mutate_
  • Использует mutate_