汇总所有列

时间:2015-01-22 17:54:01

标签: r dplyr summarization

我有以下格式的数据:

gen = function () sample.int(10, replace = TRUE)
x = data.frame(A = gen(), C = gen(), G = gen(), T = gen())

我现在想要在每一行中附加行中所有元素的总和(我的实际函数更复杂但sum说明了问题)。

没有dplyr,我会写

cbind(x, Sum = apply(x, 1, sum))

导致:

   A C  G T Sum
1  3 1  6 9  19
2  3 4  3 3  13
3  3 1 10 5  19
4  7 2  1 6  16
…

但是用dplyr做这件事似乎很难。

我试过

x %>% rowwise() %>% mutate(Sum = sum(A : T))

但结果不是每一行的总和,它是意想不到的东西,(对我来说)莫名其妙。

我也试过

x %>% rowwise() %>% mutate(Sum = sum(.))

但是在这里,.只是整个 x的占位符。不出所料,提供 no 参数也不起作用(结果都是0)。毋庸置疑,这些变体都不能在没有rowwise()的情况下发挥作用。

(在dplyr中没有任何理由必须这样做,但是(a)我希望尽可能保持我的代码统一,并且在不同的API之间跳转并没有帮助;并且(b)我我希望有一天能在dplyr中自动并自由地并行化这些命令。)

3 个答案:

答案 0 :(得分:5)

我曾经做过类似的事情,到那时我最终得到了:

x %>%
  rowwise() %>%
  do(data.frame(., res = sum(unlist(.))))
#    A  C G  T res
# 1  3  2 8  6  19
# 2  6  1 7 10  24
# 3  4  8 6  7  25
# 4  6  4 7  8  25
# 5  6 10 7  2  25
# 6  7  1 2  2  12
# 7  5  4 8  5  22
# 8  9  2 3  2  16
# 9  3  4 7  6  20
# 10 7  5 3  9  24

也许你的更复杂的功能在没有unlist的情况下工作正常,但似乎sum是必要的。由于.是指"当前组",我最初认为.例如rowwise x[1, ]机制中的第一行对应sum,这是一个列表,dois.list((x[1, ])) # [1] TRUE sum(x[1, ]) # [1] 19 之外快乐吞下

unlist

但是,如果do中没有x %>% rowwise() %>% do(data.frame(., res = sum(.))) # Error in sum(.) : invalid 'type' (list) of argument ,则会生成错误,我不确定原因:

{{1}}

答案 1 :(得分:3)

这是否符合您的要求?

Data %>%
   mutate(SumVar=rowSums(.))

答案 2 :(得分:1)

我会尝试展示我在评论中写的内容的一个例子。我们假设您有一个自定义函数f

f <- function(vec) sum(vec)^2

并且您希望将此函数应用于data.frame x的每一行。基数R中的一个选项是使用apply,如您在问题中所示:

> transform(x, z = apply(x, 1, f))
#   A  C  G T   z
#1  5  7 10 7 841
#2  1  9  5 9 576
#3  7 10  2 4 529
#4  1  4 10 1 256
#5  4  4  5 2 225
#6  9  1  6 8 576
#7  9  3  7 1 400
#8  5  2  7 5 361
#9  6  3 10 4 529
#10 5 10  1 6 484

这里的缺点是,因为您在data.frame上使用apply,所以整个data.frame首先转换为matrix,这当然意味着所有列都转换为同类型。

使用dplyr(和tidyr)你可以解决收集/融化和传播/施放后的问题。

library(dplyr)
library(tidyr)
x %>% 
  mutate(n = row_number()) %>%    # add row numbers for grouping 
  gather(key, value, A:T) %>%
  group_by(n) %>% 
  mutate(z = f(value)) %>%
  ungroup() %>%
  spread(key, value) %>%
  select(-n)

#Source: local data frame [10 x 5]
#
#     z A  C  G T
#1  841 5  7 10 7
#2  576 1  9  5 9
#3  529 7 10  2 4
#4  256 1  4 10 1
#5  225 4  4  5 2
#6  576 9  1  6 8
#7  400 9  3  7 1
#8  361 5  2  7 5
#9  529 6  3 10 4
#10 484 5 10  1 6

这显然是比使用apply更长的代码,但是一旦数据变得更大,我希望这比数据行上的任何apply快得多.frame。

或者,如果您手动指定列,则可以使用rowwise

x %>%
  rowwise %>%
  mutate(z = f(c(A,C,G,T)))  # manual column specification

#Source: local data frame [10 x 5]
#Groups: <by row>
# 
#  A  C  G T   z
#1  5  7 10 7 841
#2  1  9  5 9 576
#3  7 10  2 4 529
#4  1  4 10 1 256
#5  4  4  5 2 225
#6  9  1  6 8 576
#7  9  3  7 1 400
#8  5  2  7 5 361
#9  6  3 10 4 529
#10 5 10  1 6 484

我还没想到,如果可以更改rowwise解决方案,以便它可以使用列名的字符输入 - 也许是以某种方式使用lazyeval。

数据:

set.seed(16457)
gen = function () sample.int(10, replace = TRUE)
x = data.frame(A = gen(), C = gen(), G = gen(), T = gen())