在Matlab中构造一个元素正好是它们的索引的矩阵的最佳方法是什么?
编辑:此问题的现有答案适用于如何构建其元素为其索引的函数的矩阵。所以我把它添加到问题标题中。
格式可以是带矢量作为元素的矩阵,也可以是两个矩阵,每个矩阵存储一个索引。
最后,我想创建一个矩阵,其元素是其索引的函数。因此非常感谢一种有效的方法(但可能不同)。对效率的任何评论都受到欢迎。
对于我的应用程序,矩阵的大小往往很大(最小数百平方)。因此,利用原生Matlab函数的方法可能比for / while循环要好得多。
例如,对于大小为[2 2]的矩阵,我想制作
IND =
[1 1] [1 2]
[2 1] [2 2]
或
X =
1 1
2 2
Y =
1 2
1 2
最后,我希望做一些像
这样的事情matrixIneed = arrayfun(@(s)..., IND)
其中s是大小为2的向量,或
matrixIneed = arrayfun(@(i,j)..., X,Y)
后者是首选。
编辑:关于已接受答案的说明。
我接受了安德鲁的答案,因为这对我来说很直观,代码似乎很快(至少对我来说)。
如果你曾经谷歌这个问题的答案,你可能会像我一样关注性能。 (否则,如果不是最佳实践,任何人都可以考虑使用双循环来完成任务。)
如果是这样,我们鼓励您检查Andrew对reshape()
函数和Rody关于meshgrid()
和loops
的效果的答案的评论。
尽管如此,使用meshgrid()
的thewaywewalk解决方案是学习meshgrid()
功能的有用示例。它在许多其他Matlab函数中都很有用。
Jigg的repmat()
解决方案也可以为您提供帮助。
答案 0 :(得分:7)
使用meshgrid
或ndgrid
:
% example matrix
Matrix = magic(5)
[n m] = size(Matrix)
% or define the dimensions directly
n = 5;
m = 5;
[X,Y] = meshgrid(1:n,1:m) %\\ [Y,X] = ndgrid(1:n,1:m)
(2D情况的区别在于,Y
和X
已交换。 - 根据您的需要使用它。)
[X,Y] = meshgrid(xgv,ygv)
将网格向量xgv
和ygv
复制到 产生一个完整的网格。该网格由输出坐标表示 数组X
和Y
。输出坐标数组X
和Y
包含 分别为网格向量xgv
和ygv
的副本。的大小 输出数组由网格矢量的长度决定。对于 网格向量xgv
和ygv
分别为M
和N
,X
和Y
将 有N
行和M
列。
嗯,没有更多的解释,meshgrid
用于从两个向量创建一个常规网格,通常是“x
”和“y
”值,以获得合适的输入z
- 数据的3D /颜色编码图的数据。如果您认为x
和y
是向量[1 2 3 ... n]
,那么它就完全符合您的要求。
返回:
X =
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
Y =
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
4 4 4 4 4
5 5 5 5 5
答案 1 :(得分:4)
习惯ndgrid
。避免使用meshgrid
,但支持绘图和图形操作。
ndgrid
的输出,以行,列等表示,对于MATLAB矩阵运算具有比由meshgrid
返回的x,y坐标更自然的精确度。
>> nrows = 3;
>> ncols = 4;
>> [II,JJ] = ndgrid(1:nrows,1:ncols)
II =
1 1 1 1
2 2 2 2
3 3 3 3
JJ =
1 2 3 4
1 2 3 4
1 2 3 4
MATLAB的维度排序是行作为第一维,列作为第二维,然后是更高维。 ndgrid
遵循此约定,其输入和输出的顺序。作为参考,等效的meshgrid
命令是[JJ,II] = meshgrid(1:ncols,1:nrows);
。
为什么你应该坚持行,列的心态转换为线性索引:sub2ind
的一个很好的例子。函数sub2ind
期望订阅的顺序与ndgrid
:
>> inds = sub2ind([nrows ncols],II,JJ)
inds =
1 4 7 10
2 5 8 11
3 6 9 12
如果你总是考虑行,列(下标)而不是x,y,那么制定这个命令几乎不需要考虑。
再次使用ndgrid
。
答案 2 :(得分:3)
查看ind2sub
,sub2ind
和reshape
函数。它们对于转换多维数组上的下标和索引非常有用。
在你的情况下,看起来你想要这个。 (我认为你想要“下标”而不是“索引”。当将数组视为一维向量时,Matlab使用“index”表示元素的“线性”索引,而“下标”表示每个元素的位置多维数组的维度。)
sz = [3 3]; % Size of your matrix
n = prod(sz); % Total number of elements in matrix
[X, Y] = ind2sub(sz, 1:n); % Subscripts, returned as vectors
X = reshape(X, sz); % Reshape the subscript vectors to match your matrix
Y = reshape(Y, sz);
@thewaywewalk提供的meshgrid
方法将产生相同的输出,但我认为ind2sub
方法在这种情况下更具可读性,因为它的数据索引方面的措辞,这是你的问题域。它将概括为处理切片或数组的任意子集,meshgrid
不会,并且与ind2sub
很好地对应,以便以另一种方式进行有效的操作。 (无论如何,它值得学习meshgrid
;它会在其他位置弹出。)
答案 3 :(得分:1)
既然你已经表明你想在索引上运行一个函数,那么它是最简单的,也可能是最快的只做一个双循环:
matrixIneed = zeros(n,m);
for ii = 1:n
for jj = 1:m
matrixIneed(ii,jj) = myFunction(ii,jj);
end
end
取决于myFunction
,这可能比arrayfun
更快,当meshgrid
或n
时,内存密集度明显低于m
比较大;另见this related question。
如果您正在运行MATLAB R2009或更高版本,并且您的函数是内置函数或只能使用内置函数构建,则这些循环与meshgrid
的执行时间将具有可比性,但{ {1}}将消耗更多的内存(O(N²)内存,而不是O(1)用于循环)。与往常一样,分析是关键,但双循环可能是最好的全面解决方案。
有时候,这也会有所帮助:
meshgrid
答案 4 :(得分:0)
使用repmat
的另一个选项(因为这些矩阵的内容是多余的):
X=repmat((1:size(YourMatrix, 2))', 1, size(YourMatrix, 1));
Y=repmat(1:size(YourMatrix, 1), size(YourMatrix, 2), 1);