dplyr中跨多列转换

8

我有一个dplyr的问题:如何在不手动写出每一列的情况下使用transmute?是否有像transmute_each()这样的东西?

我想要做以下事情:使用dplyr,我想为下面的MWE获取每一列的z-score:

tickers <- c(rep(1,10),rep(2,10))
df <- data.frame(cbind(tickers,rep(1:20),rep(2:21),rep(2:21),rep(4:23),rep(3:22)))
colnames(df) <- c("tickers","col1","col2","col3","col4","col5")
df %>%  group_by(tickers)

有没有简单的方法使用 transmute 来实现以下内容:
for(i in 2:ncol(df)){
  df[,i] <- df[,i] - mean(df[,i])/sd(df[,i])
}

非常感谢


只需使用mutate_each,然后删除不需要的列即可。 - Hong Ooi
谢谢@Hongooi,这是我最初想做的事情,但我也希望有一个类似于transmute_each的包装器。 - Nick
1
据我所知,dplyr目前没有transmute_each函数,但是你可以自己定义它,例如使用transmute_each <- function(tbl, funs, ...) {mutate_each(tbl, funs, ...) %>% select(...)} - talat
2个回答

6

现在有一个transmute_at()函数(自dplyr 0.7起),您可以执行以下操作:

df %>% 
    group_by(tickers) %>% 
    transmute_at(.vars = vars(starts_with("col")),
                 .funs = funs(scale(.))) %>% 
    ungroup

请注意,这里使用了基础R中的scale()函数,默认将数值向量转换为z分数。
此外,在.vars参数中使用vars()允许您使用所有可用于dplyr的select()的辅助函数,例如one_of()ends_with()等。
最后,不必在这里编写funs(scale(.)),因为您在.funs参数中使用了一个简单的函数,所以可以直接写.funs = scale

1
我使用以下方法解决了这个问题:

df %>%  
   group_by(tickers) %>%  
   mutate_at(.funs = funs((. - mean(.))/sd(.)),
             .cols = vars(matches("col")))

3
请注意,对于假设的transmute_each函数来说,这并不是一个特别好的使用案例,因为除了分组列(无法删除)外,_所有_列都满足您的选择条件(matches("col"))。这意味着在这种情况下,transmute_each将与mutate_each执行相同的操作。 - talat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接