Используя '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
для этих типов операций?
Ответы
Ответ 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_