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
重复了基准测试- 原始数据。
- 原始数据。
- 简化的数据。表版本,
- 简化的data.frame版本,
- 矩阵版本。
结果
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")