0

这是我正在尝试做的一个例子。

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 循环来做,但它很慢。我会喜欢任何关于如何提高效率的建议。谢谢你的帮助!

4

4 回答 4

1

使用旨在快速计算产品的库,然后将结果存储在 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 
于 2020-08-13T22:27:26.383 回答
0

这是一个基本的 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
于 2020-08-12T22:48:34.440 回答
0

认为这比你的方法快一点

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)]
于 2020-08-12T21:10:22.277 回答
0

这是一种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
于 2020-08-12T20:09:14.813 回答