跨表相乘时如何加速我的 R 代码?
How can I speed up my R code when multiplying across tables?
这是我正在尝试做的一个例子。
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", "B", "D")) {
dtA[, (COL) := get(COL) * dtB[id == COL, multi]]
}
我需要使用 dtB 中的 id 列将 dtA 中的列乘以乘数,以确定要将哪一列乘以哪个因子。我可以用 for 循环来做,但它很慢。我会喜欢任何关于如何提高效率的建议。感谢您的帮助!
这是一个 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,y) x*y, dtA, dtB[cn, multi, 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
使用旨在快速计算乘积然后以 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=rowprods(x))),c("mult1","mult2","prod"))[])
user system elapsed
0.12 0.08 0.21
这是我正在尝试做的一个例子。
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", "B", "D")) {
dtA[, (COL) := get(COL) * dtB[id == COL, multi]]
}
我需要使用 dtB 中的 id 列将 dtA 中的列乘以乘数,以确定要将哪一列乘以哪个因子。我可以用 for 循环来做,但它很慢。我会喜欢任何关于如何提高效率的建议。感谢您的帮助!
这是一个 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,y) x*y, dtA, dtB[cn, multi, 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
使用旨在快速计算乘积然后以 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=rowprods(x))),c("mult1","mult2","prod"))[])
user system elapsed
0.12 0.08 0.21