如何解决跨表乘法时如何加快我的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
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。