用聚合解决ddply任务的优雅方法(希望获得更好的性能)

Joh*_*nes 7 aggregate r plyr

我想data.frame通过一个名为变量的标识符变量来聚合ensg.数据框如下所示:

  chromosome probeset               ensg symbol    XXA_00    XXA_36    XXB_00
1          X  4938842 ENSMUSG00000000003   Pbsn  4.796123  4.737717  5.326664
Run Code Online (Sandbox Code Playgroud)

我想计算具有相同ensg值的行上每个数字列的平均值.这里的问题是我想保留其他身份变量染色体和符号不变,因为它们也是相同的ensg.

最后,我想有一个data.frame带有标识列chromosome,ensg,symbol并在具有相同标识符行数值列的意思.我实现了这个ddply,但与以下相比它非常慢aggregate:

spec.mean <- function(eset.piece)
  {
    cbind(eset.piece[1,-numeric.columns],t(colMeans(eset.piece[,numeric.columns])))
  }
t
mean.eset <- ddply(eset.consensus.grand,.(ensg),spec.mean,.progress="tk")
Run Code Online (Sandbox Code Playgroud)

我的第一个聚合实现看起来像这样,

mean.eset=aggregate(eset[,numeric.columns], by=list(eset$ensg), FUN=mean, na.rm=TRUE);
Run Code Online (Sandbox Code Playgroud)

并且要快得多.但问题aggregate是我必须重新描述描述变量.我还没有弄清楚如何使用我的自定义函数,aggregate因为aggregate它不传递数据帧而只传递矢量.

是否有一种优雅的方式来做到这一点aggregate?或者有更快的方法来做到这一点ddply

Cha*_*ase 8

如果速度是主要考虑因素,您应该看看data.table包装.当行数或分组列数很大时,data.table真的好像很闪耀.包的维基是在这里,并有几个链接到其他好的介绍性文件.

以下是您如何进行此聚合的方法 data.table()

library(data.table)
#Turn the data.frame above into a data.table
dt <- data.table(df)
#Aggregation

  dt[, list(XXA_00 = .Internal(mean(XXA_00)),
          XXA_36 = .Internal(mean(XXA_36)),
          XXB_00 = .Internal(mean(XXB_00))),
    by = c("ensg", "chromosome", "symbol")
   ]
Run Code Online (Sandbox Code Playgroud)

给我们

     ensg chromosome symbol      XXA_00      XXA_36    XXB_00
[1,]   E1          A     S1  0.18026869  0.13118997 0.6558433
[2,]   E2          B     S2 -0.48830539  0.24235537 0.5971377
[3,]   E3          C     S3 -0.04786984 -0.03139901 0.5618208
Run Code Online (Sandbox Code Playgroud)

通过比较rbenchmark软件包的输出,使用30行data.frame时,上面提供的聚合解决方案似乎相当不错.但是,当data.frame包含3e5行时,data.table()作为一个明显的赢家拉开.这是输出:

 benchmark(fag(), fdt(), replications = 10)
   test replications elapsed relative user.self sys.self 
1 fag()           10   12.71 23.98113     12.40     0.31     
2 fdt()           10    0.53  1.00000      0.48     0.05         
Run Code Online (Sandbox Code Playgroud)

  • 您可以使用`mean.default`代替`mean`来避免方法调度,这可以节省您一点时间.我不介意将`.Internal`显示为_option_,只要它后面跟着"here be dragons"警告. (2认同)

Osc*_*ñán 7

首先让我们定义一个玩具示例:

df <- data.frame(chromosome = gl(3,  10,  labels = c('A',  'B',  'C')),
             probeset = gl(3,  10,  labels = c('X',  'Y',  'Z')),
             ensg =  gl(3,  10,  labels = c('E1',  'E2',  'E3')),
             symbol = gl(3,  10,  labels = c('S1',  'S2',  'S3')),
             XXA_00 = rnorm(30),
             XXA_36 = rnorm(30),
             XXB_00 = rnorm(30))
Run Code Online (Sandbox Code Playgroud)

然后我们使用aggregate公式界面:

df1 <- aggregate(cbind(XXA_00, XXA_36, XXB_00) ~ ensg + chromosome + symbol,  
    data = df,  FUN = mean)

> df1
  ensg chromosome symbol      XXA_00      XXA_36      XXB_00
1   E1          A     S1 -0.02533499 -0.06150447 -0.01234508
2   E2          B     S2 -0.25165987  0.02494902 -0.01116426
3   E3          C     S3  0.09454154 -0.48468517 -0.25644569
Run Code Online (Sandbox Code Playgroud)

  • @Johannes:FWIW,公式界面比其他界面慢. (3认同)