跨表乘法时如何加快我的R代码?

问题描述

这是我要做的事的一个例子。

dtA <- data.table(A = 1:3,B = 4:6,D = 7:9)
dtB <- data.table(id = c("A","B","C","D"),multi = c(0.1,0.2,0.3,0.4))


for(COL in c("A","D")) {
  dtA[,(COL) := get(COL) * dtB[id == COL,multi]] 
}

我需要使用dtB中的id列将dtA中的列乘以乘数,以标识要乘以哪个因子的列。我可以用for循环来做,但是非常慢。我希望就如何提高效率提出任何建议。感谢您的帮助!

解决方法

使用旨在快速计算产品的库,然后将结果以data.table或其他格式存储,可能会为您提供最好的服务。例如,“ Rfast”针对矩阵的数值计算进行了优化。 R'data.table'非常适合存储和检索大型数据表,但默认情况下存储为(R)列表:

library(data.table)
library(Rfast)

# https://rdrr.io/cran/Rfast/man/
# https://github.com/RfastOfficial/Rfast
# install.packages("Rfast")

x <- matrnorm(10^7,2)

dt <- setnames(as.data.table(cbind(x,prod=rowprods(x))),c("mult1","mult2","prod"))[]

object.size(dt)
240001544 bytes
dt
               mult1      mult2       prod
       1: -0.8085044 -1.9285537  1.5592442
       2: -1.5677905 -1.5577447  2.4422173
       3:  0.5049556 -0.2790959 -0.1409310
       4: -0.4603246  0.7289480 -0.3355527
       5:  1.4131808 -1.0857271 -1.5343287
      ---                                 
 9999996:  0.2373198 -0.7700162 -0.1827401
 9999997: -1.4357042  0.9946241 -1.4279859
 9999998:  1.1464551  0.1137755  0.1304385
 9999999:  0.3204307 -0.9189214 -0.2944506
10000000:  1.5800871 -1.3029509 -2.0587759

x <- matrnorm(10^7,2)
system.time(setnames(as.data.table(cbind(x,"prod"))[])
       user  system elapsed 
       0.12    0.08    0.21 
,

这是一种data.table方法。.可能不是最聪明的方法..但是它可以完成工作。

library( data.table )
#melt dtA to long format
dtA.melt <- melt( dtA,measure.vars = names(dtA),variable.factor = FALSE)
#set integers to numeric
dtA.melt[,value := as.numeric(value)]
#update the value column using a join
dtA.melt[ dtB,value := as.numeric(value) * i.multi,on = .(variable = id)]
#and bind back the columns
do.call( cbind,split( dtA.melt,by = "variable",keep.by = FALSE ) )

#    A.value B.value D.value
# 1:     0.1     0.8     2.8
# 2:     0.2     1.0     3.2
# 3:     0.3     1.2     3.6
,

认为这比您的方法快一点

vec <- dtB[colnames(dtA),multi,on = 'id']
dtA <- as.data.table(mapply(function(x,y) x*y,dtA,vec,SIMPLIFY = FALSE))

不过,我真的看不到可以在哪里显着提高速度,因为我认为您的尝试并没有做任何特别浪费的事情。

编辑:

这在大型示例中又快了约50%

cn <- colnames(dtA)
dtA[,(cn) := mapply(function(x,dtB[cn,on = 'id'],SIMPLIFY = FALSE)]
,

这是基本的R方法

as.data.table(t(t(dtA) * with(dtB,multi[match(names(dtA),id)])))

给出

     A   B   D
1: 0.1 0.8 2.8
2: 0.2 1.0 3.2
3: 0.3 1.2 3.6

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...