У меня есть data.frame, такой как это (у реального набора данных есть много больше строк и столбцов)
set.seed(15)
dd <- data.frame(id=letters[1:4], matrix(runif(5*4), nrow=4))
# id X1 X2 X3 X4 X5
# 1 a 0.6021140 0.3670719 0.6872308 0.5090904 0.4474437
# 2 b 0.1950439 0.9888592 0.8314290 0.7066286 0.9646670
# 3 c 0.9664587 0.8151934 0.1046694 0.8623137 0.1411871
# 4 d 0.6509055 0.2539684 0.6461509 0.8417851 0.7767125
Я хотел бы иметь возможность написать инструкцию dplyr, где я могу выбрать подмножество столбцов и мутировать их. (Я пытаюсь сделать что-то похожее на использование .SDcols в data.table).
Для упрощенного примера здесь функция, которую я хотел бы написать, чтобы добавлять столбцы для сумм и средств четных столбцов "X", сохраняя при этом все остальные столбцы. Желаемый выход с использованием базы R равен
(cols<-paste0("X", c(2,4)))
# [1] "X2" "X4"
cbind(dd,evensum=rowSums(dd[,cols]),evenmean=rowMeans(dd[,cols]))
# id X1 X2 X3 X4 X5 evensum evenmean
# 1 a 0.6021140 0.3670719 0.6872308 0.5090904 0.4474437 0.8761623 0.4380811
# 2 b 0.1950439 0.9888592 0.8314290 0.7066286 0.9646670 1.6954878 0.8477439
# 3 c 0.9664587 0.8151934 0.1046694 0.8623137 0.1411871 1.6775071 0.8387535
# 4 d 0.6509055 0.2539684 0.6461509 0.8417851 0.7767125 1.0957535 0.5478768
но я хотел использовать цепочку типа dplyr, чтобы сделать то же самое. В общем случае я хотел бы использовать любую вспомогательную функцию select()
, такую как starts_with
, ends_with
, matches
и т.д. И любую функцию. Вот что я пробовал
library(dplyr)
partial_mutate1 <- function(x, colspec, ...) {
select_(x, .dots=list(lazyeval::lazy(colspec))) %>%
transmute_(.dots=lazyeval::lazy_dots(...)) %>%
cbind(x,.)
}
dd %>% partial_mutate1(num_range("X", c(2,4)),
evensum=rowSums(.), evenmean=rowMeans(.))
Однако это выдает сообщение об ошибке
Error in rowSums(.) : 'x' must be numeric
Это похоже на то, что .
похоже ссылается на весь файл date.frame, а не на выбранное подмножество. (такая же ошибка, как rowSums(dd)
). Однако обратите внимание, что это дает желаемый результат
partial_mutate2 <- function(x, colspec) {
select_(x, .dots=list(lazyeval::lazy(colspec))) %>%
transmute(evensum=rowSums(.), evenmean=rowMeans(.)) %>%
cbind(x,.)
}
dd %>% partial_mutate2(seq(2,ncol(dd),2))
Я предполагаю, что это какая-то проблема с окружающей средой? Любые предложения о том, как передать аргументы partial_mutate1
, чтобы .
правильно принял значения из набора данных select() - ed?