我想做一个简单的列(Nx1)次行(1xM)乘法,得到(NxM)矩阵。 我按顺序创建行的代码,通过转置类似的序列来创建列
row1 <- seq(1:6)
col1 <- t(seq(1:6))
col1 * row1
表示R认为矩阵更像列
的输出 [,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 4 9 16 25 36
预期输出:NxM矩阵。
操作系统:Debian 8.5答案 0 :(得分:1)
在这种情况下,使用outer
将是一个更自然的选择
outer(1:6, 1:6)
一般情况下,对于两个数值向量 x
和y
,矩阵rank-1运算可以计算为
outer(x, y)
如果您想使用实际矩阵乘法例程,请使用tcrossprod
:
tcrossprod(x, y)
如果您的x
和y
中的任何一个是带尺寸的矩阵,请先使用as.numeric
将其转换为矢量。
建议不要使用通用矩阵乘法运算"%*%"
。但是,如果您愿意,请确保您获得可投影的维度:x
是一列矩阵,y
是一行矩阵,因此x %*% y
。
你能谈谈效率吗?
已知Matrix rank-1操作受内存限制。因此,请确保我们使用gc()
进行垃圾收集,告诉R在每次复制后从堆中释放内存(否则系统会停止):
x <- runif(500)
y <- runif(500)
xx <- matrix(x, ncol = 1)
yy <- matrix(y, nrow = 1)
system.time(replicate(200, {outer(x,y); gc();}))
# user system elapsed
# 4.484 0.324 4.837
system.time(replicate(200, {tcrossprod(x,y); gc();}))
# user system elapsed
# 4.320 0.324 4.653
system.time(replicate(200, {xx %*% yy; gc();}))
# user system elapsed
# 4.372 0.324 4.708
在表现方面,它们都非常相似。
<强>后续强>
当我回来时,我看到了另一个不同基准的答案。嗯,问题是,取决于问题的大小。如果您只是尝试一个小例子,则无法消除所有三个函数的函数解释/调用开销。如果你这样做
x <- y <- runif(500)
microbenchmark(tcrossprod(x,y), x %*% t(y), outer(x,y), times = 200)
你会再次看到大致相同的表现。
#Unit: milliseconds
# expr min lq mean median uq max neval cld
# tcrossprod(x, y) 2.09644 2.42466 3.402483 2.60424 3.94238 35.52176 200 a
# x %*% t(y) 2.22520 2.55678 3.707261 2.66722 4.05046 37.11660 200 a
# outer(x, y) 2.08496 2.55424 3.695660 2.69512 4.08938 35.41044 200 a
答案 1 :(得分:1)
这里&#39;当使用的向量长度为100时,三种方法的执行速度进行比较。最快的是tcrossprod
,x%*%t(y)
的长度增加17%{{1}延长45%(中位时间)。
在表中,outer(x,y)
是评估函数以获得基准分数的次数。
neval
要获得以下图表,请
> x <- runif(100,0,100)
> y <- runif(100,0,100)
> microbenchmark(tcrossprod(x,y), x%*%t(y), outer(x,y), times=5000)
Unit: microseconds
expr min lq mean median uq max neval
tcrossprod(x, y) 11.404 16.6140 50.42392 17.7300 18.7555 5590.103 5000
x %*% t(y) 13.878 19.4315 48.80170 20.5405 21.7310 4459.517 5000
outer(x, y) 19.238 24.0810 72.05250 25.3595 26.8920 89861.855 5000
编辑:性能取决于library("ggplot2")
bench <- microbenchmark(tcrossprod(x,y), x%*%t(y), outer(x,y), times=5000)
autplot(bench)
和x
的大小,当然还有运行代码的计算机。我最初使用长度为100的向量进行基准测试,因为这是Masi所询问的。然而,看起来这三种方法对于较大的载体具有非常相似的性能。对于长度为1000的向量,三种方法的中位数时间在我的机器上相差5%。
y
答案 2 :(得分:1)
一种简单的方法是将矢量转换为矩阵
row1.mat = matrix(row1)
col1.mat = matrix(col1)
然后使用dim
查看矩阵的维度:
dim(row1.mat)
dim(col1.mat)
如果您希望产品适用于此,则需要6*1
矩阵,再乘以1*6
矩阵。因此,您需要使用col1.mat
转换t(col1.mat)
。
您可能知道矩阵产品是%*%
row1.mat %*% t(col1.mat)
此方法与其他方法的比较
library("microbenchmark")
x <- runif(1000)
y <- runif(1000)
xx = matrix(x)
yy = matrix(y)
microbenchmark(tcrossprod(x,y),x%*%t(y),outer(x,y), xx %*% t(yy), times=2000)
Unit: milliseconds
expr min lq mean median uq max neval
tcrossprod(x, y) 2.829099 3.243785 6.015880 4.801640 5.040636 77.87932 2000
x %*% t(y) 2.847175 3.251414 5.942841 4.810261 5.049474 86.53374 2000
outer(x, y) 2.886059 3.277811 5.983455 4.788054 5.074997 96.12442 2000
xx %*% t(yy) 2.868185 3.255833 6.126183 4.699884 5.056234 87.80024 2000