使用dplyr

时间:2016-12-20 16:56:12

标签: r dplyr

我想将数据帧上的几列乘以向量的值(同一列中的所有值都应乘以相同的值,根据列的不同而不同),同时将其他列保持为他们是。

由于我广泛使用dplyr,我认为使用mutate_each函数可能很有用,所以我可以同时修改所有列,但我完全迷失了fun()部分的语法。

另一方面,我读过this solution这很简单且工作正常,但只适用于所有列而不是所选列。

这是我迄今为止所做的事情:

想象一下,我想将df中的所有列,letters乘以weight_df向量,如下所示:

df = data.frame(
  letters = c("A", "B", "C", "D"),
  col1 = c(3, 3, 2, 3),
  col2 = c(2, 2, 3, 1),
  col3 = c(4, 1, 1, 3)
)
> df
  letters col1 col2 col3
1       A    3    2    4
2       B    3    2    1
3       C    2    3    1
4       D    3    1    3
> 
weight_df = c(1:3)

如果我在应用select之前使用mutate_each我会删除letters列(如预期的那样),而这不是我想要的(这是事实的一部分)矢量不是每列基础但每行基础应用!我希望相反):

df = df %>% 
  select(-letters) %>% 
  mutate_each(funs(. * weight_df))
> df
  col1 col2 col3
1    3    2    4
2    6    4    2
3    6    9    3
4    3    1    3

但如果我没有选择任何特定的列,letters中的所有值都会被移除(顺便说一句,这很有意义),但这不是我想要的,两者都不是(这个事实的一部分,因为每个列基础上都没有应用向量,而是每行基础!我希望相反):

df = df %>% 
  mutate_each(funs(. * issb_weight))
> df
  letters col1 col2 col3
1      NA    3    2    4
2      NA    6    4    2
3      NA    6    9    3
4      NA    3    1    3

(请注意,这是一个非常简单的数据框,原始的数据框有更多的行和列 - 遗憾的是,它们没有以这么简单的方式标记,也无法获得模式)

3 个答案:

答案 0 :(得分:2)

试试这个

library(plyr)
library(dplyr)

df %>% select_if(is.numeric) %>% adply(., 1, function(x) x * weight_df)

答案 1 :(得分:2)

使用dplyr。这仅过滤数字列。为选择列提供灵活性。返回新值以及所有其他列(非数字)

index <- which(sapply(df, is.numeric) == TRUE)
df[,index] <- df[,index] %>% sweep(2, weight_df, FUN="*")

> df
  letters col1 col2 col3
1       A    3    4   12
2       B    3    4    3
3       C    2    6    3
4       D    3    2    9

答案 2 :(得分:2)

这里的问题是你基本上是在尝试操作行而不是列,因此诸如mutate_*之类的方法将无效。如果您对链接问题中提出的许多矢量化方法不满意,我认为使用tydeverse(假设letters是唯一标识符),实现此目的的一种方法是首先转换为长格式,乘以单列按组然后转换回广域(不要认为这会过于高效)

library(tidyr)
library(dplyr)

df %>% 
  gather(variable, value, -letters) %>%
  group_by(letters) %>%
  mutate(value = value * weight_df) %>%
  spread(variable, value)

#Source: local data frame [4 x 4]
#Groups: letters [4]

#     letters  col1  col2  col3
# *    <fctr> <dbl> <dbl> <dbl>
#   1       A     3     4    12
#   2       B     3     4     3
#   3       C     2     6     3
#   4       D     3     2     9