嗨,假设我需要从这个data.frame中按基因进行总结。
g1 = data.frame (
gene = c( "a","a","a","a","b"),
value = c(1,200,3,5,0)
)
gene value
1 a 1
2 a 200
3 a 3
4 a 5
5 b 0
我想做的是按基因聚合,但使用返回两个变量的函数。 对于此示例,假设此函数返回平均值和中位数。
mn <- function ( x ){
return ( c( median(x), mean(x) ))
}
因为该函数返回一个向量,所以我需要调用它两次。 有没有办法将结果拆分,这样我就不必计算两次?
g1 %>%
group_by(gene) %>%
dplyr::summarize(
median = mn ( value )[1], # because mn returns a vector I need to call it twice
mean = mn ( value )[2]
) %>%
data.frame()
您可以使用 dplyr 执行此操作,尽管它不一定像其他解决方案那样直观。但是,do()
函数将起作用。注意 - 我修改了您的mn()
函数,为返回的向量分配名称。
这是do()
的参考页面。棘手的部分是如何使用 .$
表示法传入对象。
library(dplyr)
g1 = data.frame (
gene = c( "a","a","a","a","b"),
value = c(1,200,3,5,0)
)
mn <- function (x){
return(c(median = median(x), mean = mean(x)))
}
g1 %>% group_by(gene) %>%
do(data.frame(t(mn(.$value)))) %>%
data.frame()
#> gene median mean
#> 1 a 4 52.25
#> 2 b 0 0.00
创建于 2019-01-11 由 reprex 软件包 (v0.2.1)
在不深入探讨data.table
和dplyr
的情况下,以下是两种解决方案在中等大小的数据块上的时序比较:
library(data.table)
library(dplyr)
#function
mn <- function (x){
return(list(median = median(x), mean = mean(x)))
}
#bigger data
g1 = data.frame(
gene = gl(1e5, 1e2),
value = rnorm(1e8)
)
f_dt <- function() setDT(g1)[, mn(value), by = gene]
f_dp <- function() g1 %>% group_by(gene) %>% do(data.frame(t(mn(.$value)))) %>% data.frame()
system.time(f_dt())
#> user system elapsed
#> 11.00 1.53 15.35
system.time(f_dp())
#> user system elapsed
#> 38.09 0.37 39.94
创建于 2019-01-11 由 reprex 软件包 (v0.2.1)
用dplyr
做到这一点,但你可以用data.table
library(data.table)
g1 = data.table (
gene = c( "a","a","a","a","b"),
value = c(1,200,3,5,0))
mn <- function(x){
return(list(med = median(x), mean = mean(x)))
}
g1[, mn(value), by = gene]