定义三个行向量, A =(1,2,3) B =(10,20,30,40) C =(100,200,300,400,500)
我想构建一个新的矩阵D,它将具有3x4x5 = 60个元素并包含这些元素的平均值,如下所示:
D =
(1+10+100)/3, (1+10+200)/3,…, (1+10+ 500)/3 \
(1+20+100)/3, (1+20+200)/3,…, (1+20+ 500)/3 \
(1+30+100)/3, (1+30+200)/3,…, (1+30+ 500)/3 \
(1+40+100)/3, (2+40+200)/3,…, (2+40+ 500)/3 \
(2+10+100)/3, (2+10+200)/3,…, (2+10+ 500)/3 \
(2+20+100)/3, (2+20+200)/3,…, (2+20+ 500)/3 \
(2+30+100)/3, (2+30+200)/3,…, (2+30+ 500)/3 \
(2+40+100)/3, (2+40+200)/3,…, (2+40+ 500)/3 \
(3+10+100)/3, (3+10+200)/3,…, (3+10+ 500)/3 \
(3+20+100)/3, (3+20+200)/3,…, (3+20+ 500)/3 \
(3+30+100)/3, (3+30+200)/3,…, (3+30+ 500)/3 \
(3+40+100)/3, (3+40+200)/3,…, (3+40+ 500)/3 \
在这个例子中它的设置方式是12x5矩阵,但如果它是1X60矢量或60X1矢量我就没问题了。
如何在Mata中有效地完成这项工作?我是Mata的新手,我使用多个forval
循环在Stata中运行(在这种情况下,会有3个forval
循环)。但这变得非常耗时,因为我有多达8个行向量和每个向量约120个元素。
我认为我可以在Mata中使用for
循环并且它会更快,但我相信如果我可以将其作为矩阵操作而不是使用for
循环,那么它将是均匀的快点。问题是我很难想象如何编写这样的程序(或者甚至可能),任何帮助都会受到高度赞赏。
答案 0 :(得分:1)
对于较小的示例,您基本上要求的是Kronecker产品的总和版本。我在这个主题上发现了这个Matlab讨论thread,其中它被称为Tensor Sum(没有经常使用这个短语)。
这是在Mata中复制操作的快速尝试。不是一个非常简洁的代码,所以随时编辑或更正。
clear
mata
// input data
A=(1,2,3)' // 3x1
B=(10,20,30,40)' // 4x1
C=(100,200,300,400,500)' // 5x1
// tensor sum for A and B
a=J(1,4,1) // 1x4 with values of 1
b=J(1,3,1) // 1x3 with values of 1
T=(A#a)+(b#B)'
T // 3x4
T=vec(T) // 12x1
// tensor sum for T and C
c=J(1,12,1) // 1x12 with values of 1
t=J(1,5,1) // 1x5 with values of 1
T=(C#c)+(t#T)'
// divide by 3
T=T/3
T' // transposed just for better display
end
答案 1 :(得分:1)
@AspenChen的聪明解决方案比for
循环提供了巨大的速度提升,如某些测试所示:
clear all
set more off
mata
timer_clear()
//----- change data -----
fa = 250
fb = fa + 1
fc = fa + 2
//----- Method 1 -----
timer_on(1)
A = (1..fa) // 1 x fa
B = (1..fb)*10 // 1 x fb
C = (1..fc)*100 // 1 x fc
F = J(1, cols(A) * cols(B) * cols(C), .)
col = 0
for (i=1; i<=cols(A); i++) {
for (j=1; j<=cols(B); j++) {
for (k=1; k<=cols(C); k++) {
col++
F[1,col] = A[1,i] + B[1,j] + C[1,k]
}
}
}
timer_off(1)
//----- Method 2 (Aspen Chen) -----
timer_on(2)
A = (1::fa) // fa x 1
B = (1::fb)*10 // fb x 1
C = (1::fc)*100 // fc x 1
// tensor sum for A and B
a = J(1,rows(B),1) // 1 x fb with values of 1
b = J(1,rows(A),1) // 1 x fa with values of 1
T = (A#a) + (b#B)' // fa x fb
T = vec(T) // fa*fb x 1
// tensor sum for T and C
c = J(1,rows(T),1) // 1 x fa*fb with values of 1
t = J(1,rows(C),1) // 1 x fc with values of 1
T = (C#c) + (t#T)' // fc x fa*fb
timer_off(2)
timer()
end
导致:
timer report
1. 8.78 / 1 = 8.776
2. .803 / 1 = .803
如果原始海报仍然想要使用for
循环,因为要比较大量的元素,他可以使用以下内容:
<snip>
larger = 0
for (i=1; i<=cols(A); i++) {
for (j=1; j<=cols(B); j++) {
for (k=1; k<=cols(C); k++) {
larger = larger + (A[1,i] + B[1,j] + C[1,k] > 7)
}
}
}
larger
<snip>
仅使用for
循环进行进一步测试:
clear all
set more off
mata
timer_clear()
//----- change data -----
fa = 500
fb = fa + 1
fc = fa + 2
//----- Method 1 -----
timer_on(1)
A = (1..fa) // 1 x fa
B = (1..fb)*10 // 1 x fb
C = (1..fc)*100 // 1 x fc
larger = 0
for (i=1; i<=cols(A); i++) {
for (j=1; j<=cols(B); j++) {
for (k=1; k<=cols(C); k++) {
larger = larger + (A[1,i] + B[1,j] + C[1,k] > 7)
}
}
}
larger
timer_off(1)
//----- Method 2 (ec27) -----
timer_on(2)
A = (1..fa) // 1 x fa
B = (1..fb)*10 // 1 x fb
C = (1..fc)*100 // 1 x fc
larger = 0
for (i=1; i<=cols(A); i++) {
for (j=1; j<=cols(B); j++) {
for (k=1; k<=cols(C); k++) {
placebo = A[1,i] + B[1,j] + C[1,k]
if (placebo > 7) larger = larger + 1
}
}
}
larger
timer_off(2)
timer()
end