我有以下格式的数据:
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中自动并自由地并行化这些命令。)
答案 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
,这是一个列表,do
在is.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())