у меня есть data.frame, такие как это (реальный набор данных имеет гораздо больше строк и столбцов)Выполнение dplyr мутировать на подмножества столбцов
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).
Для упрощенного примера, вот функция, которую я хотел бы написать для добавления столбцов для сумм и средств четных столбцов «Х» при сохранении всех остальных столбцов. Желаемый выход с использованием основания 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»?
Безобразная способом было бы: 'дд%>% выбора (Х2, Х4)%>% мутируют (evensum = rowSums(), evenmean = rowMeans()..)%>% выберите (- X2, -X4)%>% cbind (., Dd) ' –
Я подозреваю, что проблема в том, что попытка SE возится с '%>%'. Другими словами, с 'rowMeans (.)' Burried внутри '.dots','%>% 'не может знать, что он должен также подставлять данные. Это просто догадка. – BrodieG
Я думаю, что ты прав @BrodieG.После немного большего количества копаний это больше проблема magrittr, чем проблема dplyr. Например: 'mutate (dd [, - 1], sums = rowSums (.))' Не работает ("object '.' Not found"). Знак '.' не является особым для' dplyr'. Попытка использовать его для применения функции по столбцам кажется неправильной идеей. Думаю, я должен сначала переформатировать данные в «опрятный» формат. – MrFlick