如何将向量表的每一行与向量相乘

时间:2019-03-21 16:39:47

标签: r data.table

我有一个数据表dt,例如:

     a  b  c
[1]  1  2  3
[2]  2  3  4
[3]  3  4  5
[4]  4  5  6

我想将dt的每个中的值与向量vec中的值相乘:

vec

1  0  0

我期望输出dt得到以下结果:

     a  b  c
[1]  1  0  0
[2]  2  0  0
[3]  3  0  0
[4]  4  0  0

我已经在for循环中解决了这个问题。有没有更好的(矢量化)和更快的方法来解决此问题?有时我的数据表有成千上万的列,这就是循环变得很慢的原因。我还想保持数据表格式并避免转换。但是,最后,运行时间最快的解决方案对我来说很重要。

1 个答案:

答案 0 :(得分:3)

在相对较大的5000x5000数据表上,使用for在列上进行set循环是我能找到的最快方法。这是我尝试的其他方法,取自Multiply rows of matrix by vector。方法按性能顺序排序,尽管在此规模下后两种方法几乎无法区分。

## sample data
nr = 5000
nc = 5000
set.seed(47)
raw_matrix = matrix(rpois(nr * nc, lambda = 10), nrow = nr)
vec = rpois(nc, lambda = 2)


## For loop with set
# reset the data table
x = as.data.table(raw_matrix)
t0 = Sys.time()
for (col in 1:ncol(x)) set(x, j = col, value = x[[col]] * vec[col])
(set_time = Sys.time() - t0)
# Time difference of 0.151 secs


## Transpose and multiply
# reset the data table
x = as.data.table(raw_matrix)
t0 = Sys.time()
x <- as.data.table(t(t(x) * vec)) 
# using as.data.table because setDT does not work on matrix
(transpose_time = Sys.time() - t0)
# Time difference of 0.614 secs


## Sweep
# reset the data table
x = as.data.table(raw_matrix)
t0 = Sys.time()
setDT(x <- sweep(x, MARGIN = 2, vec, "*"))
(sweep_time = Sys.time() - t0)
# Time difference of 1.81 secs


## Make Matrix method
# reset the data table
x = as.data.table(raw_matrix)
t0 = Sys.time()
setDT(x <- x * matrix(vec, dim(x)[1], length(vec), byrow = TRUE))
(make_matrix_time = Sys.time() - t0)
# Time difference of 1.88 secs

set方法仅在您想要修改原始数据表时才有效。相反,如果您想保留原始文件并制作修改后的副本,则弗兰克(Frank)建议的方法效果很好--比修改原始文件的速度甚至稍微(当然,它需要更多的时间)内存):

##  Create modified copy
z <- setDT(Map(`*`, x, vec))