【问题标题】:dplyr how to summarize and split result from a function that returns a vectordplyr 如何汇总和拆分返回向量的函数的结果
【发布时间】:2019-01-12 03:10:03
【问题描述】:

嗨,我想我需要从这个 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()

【问题讨论】:

  • 为什么不给每个单独的函数?

标签: r dplyr


【解决方案1】:

您可以使用 dplyr 做到这一点,尽管它不一定像其他解决方案那样直观。但是,do() 函数将起作用。注意 - 我修改了您的 mn() 函数以将名称分配给返回的向量。

这是do()reference page。棘手的部分是如何使用 .$ 表示法传入对象。

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

reprex package (v0.2.1) 于 2019-01-11 创建

在不深入探讨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

reprex package (v0.2.1) 于 2019 年 1 月 11 日创建

【讨论】:

  • 这是一个有趣的解决方案。我想知道这是否会影响更大数据帧的速度。谢谢。
  • @Ahdee - 我的预感是 data.table() 随着数据的扩展,将证明速度更快。
  • @Ahdee - 查看时间比较。在此示例中,data.table() 的速度提高了约 2.5 倍。
  • 另一种选择是将summarise 作为list 然后unnest 假设初始函数输出tibbledata.frame mn &lt;- function(x) tibble(median = median(x), mean = mean(x)); g1 %&gt;% group_by(gene) %&gt;% summarise(out = list(mn(value))) %&gt;% unnest
【解决方案2】:

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]

【讨论】:

    猜你喜欢
    • 2015-06-12
    • 2016-02-06
    • 2015-06-27
    • 1970-01-01
    • 2017-09-14
    • 2018-10-22
    • 2021-01-20
    • 2015-10-06
    • 1970-01-01
    相关资源
    最近更新 更多