r-数据的转换.表似乎比data.frame所需的时间更长



i有一个大数据框(mydata((5.2G:6000ROWS,230,000列(,我需要从中征服一些列的列,其名称匹配列表中的 Name中的值( annot((,而不是将其转换为matrix。我读到该数据的速度应该更快,因此我试图将脚本转换为将mydata作为data.table而不是data.frame

到目前为止,我没有这样的印象,即当我将原始数据转换为数据时,处理速度得到提高。

一些示例数据:

mydata=read.table(text="IID A   B   E   G   H   W   Z   D   N   K
                  1 0   0   0   0   0   0   0   0   0   0
                  2 0   0   0   0   0   0   0   0   0   0
                  3 0   0   0   0   0   0   0   0   0   0
                  4 0   0   0   1   0   0   0   0   0   0
                  5 0   0   0   0   0   0   0   0   0   0
                  6 0   0   2   0   2   0   0   0   1   1
                  7 0   2   0   1   0   0   0   0   0   0
                  8 0   0   2   0   0   0   0   0   0   0
                  9 0   0   0   0   2   0   0   0   1   0
                  10    1   0   0   0   0   0   2   0   0   2
                  11    0   0   0   0   0   0   0   0   0   0
                  12    0   0   0   1   0   0   0   0   0   0
                  13    2   0   0   0   0   0   0   0   2   1
                  14    0   0   0   0   0   0   2   0   0   0
                  15    1   0   0   0   0   0   0   0   0   0
                  16    0   0   0   1   0   0   0   0   0   1
                  17    0   0   0   0   0   0   0   0   0   0
                  18    0   0   0   0   0   0   0   0   0   0
                  19    0   0   0   0   0   0   0   0   0   0
                  20    0   0   0   0   0   0   0   0   0   0",h=T)
annot=read.table(text="Name Gene
                 A  Gene1
                 B  Gene2
                 E  Gene3
                 G  Gene4
                 H  Gene5
                 W  Gene6
                 Z  Gene7
                 D  Gene8
                 N  Gene9
                 K  Gene10",stringsAsFactors=F,h=T)
genes = c("Gene2","Gene4","Gene9")

示例代码:

#as DATA FRAME    
start <- proc.time()
annot1 = annot[which(annot$Gene %in% genes),]
mydata1=mydata[,c(1,which(colnames(mydata) %in% annot1$Name))]
mydata1=mydata1[order(mydata1$IID),]
genomxwork=as.matrix(mydata1[,2:dim(mydata1)[2]])
df_time <- proc.time() - start
df_time
> utilisateur     système      écoulé 
>        0.00        0.00        0.24

相同的代码,但这次mydata转换为data.table

#as DATA TABLE
mydataDT=as.data.table(mydata)
annotDT=as.data.table(annot)
start <- proc.time()
annotDT1 = annotDT[which(Gene %in% genes),,]
mydataDT1=mydataDT[,c(1,which(colnames(mydataDT) %in% annot1$Name)),with=F]
mydataDT1=mydataDT1[order(IID),,]
genomxworkDT=as.matrix(mydatDT1[,2:dim(mydataDT1)[2]])
dt_time <- proc.time() - start
dt_time
> utilisateur     système      écoulé 
>        0.00        0.00        0.25

在示例中,差异显然并不显着,但是在我的真实数据上,当我有几千列提取时,差异很快就会上升。

这是针对90,000列的:

df_time
> utilisateur     système      écoulé 
>       10.91        0.91       12.02
dt_time
> utilisateur     système      écoulé 
>       24.00        0.00       24.15

建议的各种注释

  • 使用microbenchmark软件包,
  • 改善data.table代码,
  • 使用矩阵。

(此外,对用于基准测试的数据集的小尺寸和生产数据集的布局提出了一般关注点。(

。(

但是,我使用

microbenchmark重复了基准测试
  1. 原始数据。
  2. 原始数据。
  3. 简化的数据。表版本,
  4. 简化的data.frame版本,
  5. 矩阵版本。

结果

Unit: microseconds
    expr      min        lq       mean    median        uq      max neval
 df_orig  192.944  218.2420  235.02202  225.7940  236.9325  394.950   100
 dt_orig 1012.672 1038.1590 1104.42052 1063.2675 1093.2855 3483.561   100
     dt2  962.454  984.7315 1040.32245 1001.3445 1026.8315 3130.523   100
     df2   47.953   53.2400   64.45366   63.0565   65.6995  217.109   100
     mat    2.644    4.5310    6.46469    6.4190    7.1750   51.352   100 

使用给定的小数据集20行和11列 ,矩阵版本的速度比简化数据快十倍。帧版本比原始数据快4倍。FRAME版本。对于此简单的数据检索任务,data.table的强点不使用而无需复制。因此,难怪的是这个玩具示例的开销是主导的。

基准代码

microbenchmark::microbenchmark(
  df_orig = {
    annot1 = annot[which(annot$Gene %in% genes),]
    mydata1=mydata[,c(1,which(colnames(mydata) %in% annot1$Name))]
    mydata1=mydata1[order(mydata1$IID),]
    genomxwork=as.matrix(mydata1[,2:dim(mydata1)[2]])
  },
  dt_orig = {
    annotDT1 = annotDT[which(Gene %in% genes),,]
    mydataDT1=mydataDT[,c(1,which(colnames(mydataDT) %in% annot1$Name)),with=F]
    mydataDT1=mydataDT1[order(IID),,]
    genomxworkDT=as.matrix(mydataDT1[,2:dim(mydataDT1)[2]])
  },
  dt2 = {
    genomxworkDT <- as.matrix(mydataDT[
      , .SD, .SDcols = annotDT[J(genes), on = "Gene"]$Name])
  },
  df2 = {
    genomxwork <- as.matrix(mydata0[, names(annot_vec)[annot_vec %in% genes]])
  },
  mat = {
    genomxwork <- mat[, names(annot_vec)[annot_vec %in% genes]]
  },
  times = 100L
)

数据

数据转换为data.table和矩阵,分别是在基准之外完成的,因为在生产环境中也是如此。

mydata=read.table(text="IID A   B   E   G   H   W   Z   D   N   K
                  1 0   0   0   0   0   0   0   0   0   0
                  2 0   0   0   0   0   0   0   0   0   0
                  3 0   0   0   0   0   0   0   0   0   0
                  4 0   0   0   1   0   0   0   0   0   0
                  5 0   0   0   0   0   0   0   0   0   0
                  6 0   0   2   0   2   0   0   0   1   1
                  7 0   2   0   1   0   0   0   0   0   0
                  8 0   0   2   0   0   0   0   0   0   0
                  9 0   0   0   0   2   0   0   0   1   0
                  10    1   0   0   0   0   0   2   0   0   2
                  11    0   0   0   0   0   0   0   0   0   0
                  12    0   0   0   1   0   0   0   0   0   0
                  13    2   0   0   0   0   0   0   0   2   1
                  14    0   0   0   0   0   0   2   0   0   0
                  15    1   0   0   0   0   0   0   0   0   0
                  16    0   0   0   1   0   0   0   0   0   1
                  17    0   0   0   0   0   0   0   0   0   0
                  18    0   0   0   0   0   0   0   0   0   0
                  19    0   0   0   0   0   0   0   0   0   0
                  20    0   0   0   0   0   0   0   0   0   0",h=T)
mydataDT=as.data.table(mydata)
mat <- as.matrix(mydata[order(mydata$IID), ])
annot=read.table(text="Name Gene
                 A  Gene1
                 B  Gene2
                 E  Gene3
                 G  Gene4
                 H  Gene5
                 W  Gene6
                 Z  Gene7
                 D  Gene8
                 N  Gene9
                 K  Gene10",stringsAsFactors=F,h=T)
annotDT=as.data.table(annot)
annot_vec <- setNames(annot$Gene, annot$Name)
genes = c("Gene2","Gene4","Gene9")

最新更新