如何使用dplyr按列索引对所选列进行逐行求和?

6
dplyr 中,如何对选择的列进行逐行求和(使用列索引)?
这种方法不起作用。
> iris  %>% mutate(sum=sum(.[1:4])) %>% head
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species    sum
1          5.1         3.5          1.4         0.2  setosa 2078.7
2          4.9         3.0          1.4         0.2  setosa 2078.7
3          4.7         3.2          1.3         0.2  setosa 2078.7
4          4.6         3.1          1.5         0.2  setosa 2078.7
5          5.0         3.6          1.4         0.2  setosa 2078.7
6          5.4         3.9          1.7         0.4  setosa 2078.7

我可以完成以下操作,但不够美观。
> iris %>% mutate(index=1:n()) %>%  
                gather("param", "value", 1:4)  %>% 
                group_by(index) %>% 
                mutate(sum=sum(value)) %>% 
                spread(param, value) %>% select(-index)
Source: local data frame [150 x 6]

   Species  sum Sepal.Length Sepal.Width Petal.Length Petal.Width
1   setosa 10.2          5.1         3.5          1.4         0.2
2   setosa  9.5          4.9         3.0          1.4         0.2
3   setosa  9.4          4.7         3.2          1.3         0.2
4   setosa  9.4          4.6         3.1          1.5         0.2
5   setosa 10.2          5.0         3.6          1.4         0.2
6   setosa 11.4          5.4         3.9          1.7         0.4
7   setosa  9.7          4.6         3.4          1.4         0.3
8   setosa 10.1          5.0         3.4          1.5         0.2
9   setosa  8.9          4.4         2.9          1.4         0.2
10  setosa  9.6          4.9         3.1          1.5         0.1
..     ...  ...          ...         ...          ...         ...

有更加语法优美的方法来实现这个吗?

编辑:与其他问题不同之处在于,我想对使用列索引选择的列进行逐行操作。


7
尝试使用 iris %>% mutate(sum=Reduce("+",.[1:4]))。或者,基本的 rowSums 函数也可以实现您所要求的功能。 - nicola
dplyr 提供了 rowwise 函数,可能会有所帮助。 - SabDeM
1
如链接所示,一种选项是使用rowwisedo,即iris %>% rowwise() %>% do(data.frame(., sum=sum(unlist(.[1:4])))) - akrun
@nicola,我最喜欢你的回答。你能把它制作成一个答案让我选为最终答案吗? - Alby
@Alby,很高兴你喜欢它。我会添加一个答案。 - nicola
4个回答

12

如前面评论中所述,您可以通过以下方式完成您的任务:

iris %>% mutate(sum=Reduce("+",.[1:4]))

在这种情况下,rowSums基础函数同样适用:

iris$sum<-rowSums(iris[,1:4])

2
我知道原帖想要使用列索引,但是否有一种方法可以使用列名称呢?我在考虑像选择函数select(df, V4:V13)这样的东西。不确定如何在这里放置它。 - emudrak

1

不确定这是否是正确的礼节,但我更喜欢回收此线程,而不是开始新的线程,因为我非常确定我只是犯了一个初级错误。

为什么这样做可以正常工作:

test$sum <- Reduce("+", test[,3:ncol(test)])

而这个(对我来说是一样的)为什么不行?

test %>%
  mutate(sum = Reduce("+",.[3:ncol(.)]))

给出的错误是:
Error in mutate_impl(.data, dots) : 
  Column `sum` must be length 1 (the group size), not 915

我已经在桌子上敲了30分钟的头了!

我希望我能给你底层数据集,但实在不行。

第1列到第2列是文本字段,而第3列到第ncol(.)列是TRUE/FALSE(逻辑)字段。 ncol(.) = 33。


1
您可以滥用基本的R语言函数subset,它允许按列号选择列:
iris %>% subset(select=1:4) %>% mutate(sum=rowSums(.))

3
dplyrselect 函数似乎工作正常:iris %>% select(1:4) %>% mutate(sum=rowSums(.))..? - Frank

0

我认为逐行操作的能力是整洁语法的一个弱点,但是purrr:pmap_*很有用,可以运行这个操作,尽管它不是那么明显:

iris %>% 
  mutate(total = pmap_dbl(select(., -Species), sum))

    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species  total
1            5.1         3.5          1.4         0.2     setosa  10.2
2            4.9         3.0          1.4         0.2     setosa   9.5
3            4.7         3.2          1.3         0.2     setosa   9.4
4            4.6         3.1          1.5         0.2     setosa   9.4
5            5.0         3.6          1.4         0.2     setosa  10.2

或者你可以使用select_if(., is.numeric)代替select(., -Species),使其更加通用化(但如果有一些数值变量不想包含在计算中,则无法正常工作)。


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