R - dplyr 如何汇总和拆分返回向量的函数的结果



嗨,假设我需要从这个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.tabledplyr的情况下,以下是两种解决方案在中等大小的数据块上的时序比较:

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]

最新更新