我有一个数据框架,像这样(实际数据集有更多的行和列)
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语句,以选择列的子集并对其进行变异(我试图做类似于在data.table中使用.SDcols的事情)。
以一个简化的例子为例,这里是我想要编写的函数,用于添加偶数“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
看起来是因为 .
似乎是指整个数据框而不是所选子集。(与 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()”数据集中取值吗?
dd %>% select(X2, X4) %>% mutate(evensum = rowSums(.), evenmean = rowMeans(.)) %>% select(-X2, -X4) %>% cbind(., dd)
- Steven Beaupré%>%
。换句话说,由于rowMeans(.)
被嵌套在.dots
中,%>%
无法知道它也应该替换数据。这只是一个猜测。 - BrodieGmutate(dd[,-1], sums=rowSums(.))
不起作用("object '.' not found")。所以.
符号对于dplyr
并不是特殊的。试图使用它来跨列应用函数似乎是错误的想法。我想我应该先将数据重塑为“整洁”的格式。 - MrFlickstarts_with
和其他选择辅助函数 - @Brandon Bertelsen建议的语法现在似乎可以工作,即mutate(new_col = rowSums(select(., starts_with(string))))
。 - tjebo