我将尝试展示我在评论中所写内容的示例。假设您有一个自定义函数f
:
f <- function(vec) sum(vec)^2
并且您想将此函数应用于 data.frame x 的每一行。apply
如您在问题中所示,base R 中的一种选择是使用:
> 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
这里的小缺点是,因为您apply
在 data.frame 上使用,整个 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
data.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())