关于两层循环的问题,求助各位老师:
现在有两个矩阵(维数均不相同),需要用其每一行作为参数输入到函数中作为变量使用,如何高效运算呢?此时apply好像不好用了,只能使用foreach吗?
两层循环问题
tctcab 不是对1个矩阵的行和列分别计算。而是有两个矩阵,每次以这两个矩阵的每一行为参数输入到函数中,比如说:
a<-matrix(1:12,ncol=3)
b<-matrix(12:23,ncol=3)
qiuhe<-function(a_row,b_row,c){
final<-sum(a_row*b_row)+c
}
这里qiuhe是个简单的示例函数了(实际肯定不是求和这么简单,不然也用不着apply了)。像这样如何可能用apply呢?
- 已编辑
大概明白了,不过具体写法还得看你的目的。
假如两个矩阵行数分别为m和n
如果目的是算 m*(n-1)/2 的结果,那么还是可以写成apply函数,我想到的方法是先算出行数组合构成的辅助数据框用于apply的输入,然后在apply调用的函数中分别用两个矩阵的行数调用m,n矩阵对应的行。
不需要两重循环的原因是循环之间的计算结果没有依赖
- 已编辑
可以把矩阵转成list形式后用mapply吧
a <- as.data.frame(t(a))
b <- as.data.frame(t(b))
mapply(qiuhe, a, b, MoreArgs = list(c = 2))
这种问题个人觉得如果无法通过数学方法将你需要做的运算转换成矩阵运算的话,那就不要将数据存为矩阵,没太大意义,而且做运算的时候让人很困惑,存成list或者dataframe比较直观来着...
tctcab 谢谢您的提议!我也是因为意识到两层循环间没有依赖才在如何避免for循环上苦动脑筋。我今天下午想到的一个方法是以其中一个矩阵(整体,而不是某一行)作为目标函数的参数,并在此函数内部使用一次apply,而后只需对剩下的一个矩阵使用一次apply就好了。似乎和您的想法挺接近,我会都试试看的。再次感谢您的建议!
- 已编辑
FangGong 这个想法蛮新颖的!(对我来说),但这样却恰好捡了我此处举的例子不恰当之漏——a和b的行数刚好相同。这个方法本质上仍然没有逃脱apply家族面对多维数组的缺陷,即只能以共同的某一行或某一列为参数。具体来说,在本例中,应当是a的每一行和b的每一行相加,故而应有16种结果,而此处运用mapply只能得到4种结果,原因在其是将a的第一行与b的第一行相加,a的第二行与b的第二行相加,如此而已......不过,仍然感谢您的提议,为我打开了新思路的大门!
a <- c(1:5)
b <- c(6:10)
outer(a,b,`+`)
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 7 8 9 10 11
#> [2,] 8 9 10 11 12
#> [3,] 9 10 11 12 13
#> [4,] 10 11 12 13 14
#> [5,] 11 12 13 14 15
sapply(a,function(x) sapply(b,function(y) x+y))
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 7 8 9 10 11
#> [2,] 8 9 10 11 12
#> [3,] 9 10 11 12 13
#> [4,] 10 11 12 13 14
#> [5,] 11 12 13 14 15
<sup>Created on 2021-05-17 by the reprex package (v0.3.0)</sup>
frankzhang21 谢谢您的方法,这个注意我觉得很棒!但我对它有个疑问:这个方法似乎只能对向量使用?比如说这里的a和b仅仅为一维的向量。如果参数是个m*n维数的矩阵,它能做到对m的每一行作为参数进行计算吗?
(a <- matrix(1:20,nrow=4,byrow = TRUE))
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 1 2 3 4 5
#> [2,] 6 7 8 9 10
#> [3,] 11 12 13 14 15
#> [4,] 16 17 18 19 20
(b <- matrix(21:40,nrow=4,byrow = TRUE))
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 21 22 23 24 25
#> [2,] 26 27 28 29 30
#> [3,] 31 32 33 34 35
#> [4,] 36 37 38 39 40
sapply(seq_len(nrow(a)),function(x) sapply(seq_len(nrow(b)), function(y) mean(a[x,])+mean(b[y,])))
#> [,1] [,2] [,3] [,4]
#> [1,] 26 31 36 41
#> [2,] 31 36 41 46
#> [3,] 36 41 46 51
#> [4,] 41 46 51 56
<sup>Created on 2021-05-17 by the reprex package (v0.3.0)</sup>
嗨呀,一个道理的。取决于你matrix的每一行是怎么作为参数的。在最里面的那个function操作即可
frankzhang21 哈哈哈好的,十分感谢!我尝试尝试