我有一个 2092x252 的 double
矩阵,需要创建一个使用 bsxfun
的 for
循环。让我们说这个例子bsxfun(@minus)
.我需要循环来完成的是使用每列作为索引来运行bsxfun(@minus)
。例如,将列 1 指定为索引将得到列 2:252 的差异(使用 bsxfun(@minus)
)。然后将第 2 列设置为索引,并得到与列 3:252 的差异(再次使用 bsxfun(@minus)
)。循环必须继续运行,直到 bsxfun(@minus, 251, 252)
。
输出将在一个变量中,而不是 251 个变量中。总共有 31626 个数据点。
另外,您能否解释一下代码。
我不确定这是否正是您想要的,因为它会产生 31626x2092 个数据点,但既然你说要取列的差异......
data=ceil(rand(7,5)*10); % some sample data, works with any matrix(at least 2 columns of course)
N = size(data,2);
%b=cell(N-1,1);
c=NaN(size(data,1),N*(N-1)/2); % preallocate result matrix
kk=0;
for ii=1:N-1
%b{ii} = bsxfun(@minus,data(:,ii),data(:,ii+1:end));
c(:,kk+(1:N-ii)) = bsxfun(@minus,data(:,ii),data(:,ii+1:end));
kk=kk+N-ii;
end
这里的关键是,在每个循环步骤中,您只选择要对其执行minus
操作的矩阵部分,即:data(:,ii)
(= 第 ii 列)和 data(:,ii+1:end)
(= 所有剩余列,从第 ii 列到矩阵的末尾)
bsxfun函数描述说:
将逐个元素二进制操作应用于启用了单例扩展的两个数组
那个单例扩展是我在这里使用的,bsxfun 看到两个输入是一列和一个具有相同大小列的矩阵,并将列扩展为与矩阵大小相同的大小(=单例扩展(行维度得到扩展)
所以如果你想让行互相减去,你可以只提供一行和和以前一样的矩阵,它也会知道该怎么做,即沿列维度展开行向量:
N = size(data,1);
%b=cell(N-1,1);
c=NaN(N*(N-1)/2,size(data,2)); % preallocate result matrix
kk=0;
for ii=1:N-1
%b{ii} = bsxfun(@minus,data(ii,:),data(ii+1:end,:));
c(kk+(1:N-ii),:) = bsxfun(@minus,data(ii,:),data(ii+1:end,:));
kk=kk+N-ii;
end
如您所见,所有矩阵的索引都换了位置:A(i,j)
更改为 A(j,i)
。
循环的每个步骤中使用单元格作为结果矩阵可以更轻松地访问结果,但由于您希望结果在一个变量(我假设的矩阵)中,因此我将其注释掉。
编辑
预分配时:http://www.mathworks.nl/help/techdoc/matlab_prog/f8-784135.html
c(:,kk+(1:N-ii));
kk=kk+N-ii
是索引,这是最棘手的:
当 ii=1 时,您有 251 列要插入:这将是输出变量
中的 1->251 列ii=2 -> 250 列,输出
中的列 252->501ii=3 -> 249 列,输出
中的列 502->750ii=4 => 248 列,输出
中的列为 751->999等。
kk+(1:N-ii)
本质上是这样做的:为bsxfun
的输出选择合适的列。
变量kk
是已经保存到输出变量c
中的列数,所以显然它从零开始。如果将其更改为另一个值,例如kk_init
,c
的前 kk_init
列将保持为空,生成的c
矩阵将具有 N*(N-1)/2+kk_init
列而不是 N*(N-1)/2
列。
为了避免跟踪索引,您可以计算结果并将其存储在单元格数组中,然后将所有单元格连接成一个矩阵:
data = rand(2092,252);
C = arrayfun(@(k) bsxfun(@minus, data(:,k), data(:,k+1:end)), ...
1:size(data,2)-1, 'UniformOutput',false);
C = horzcat(C{:});
生成的矩阵:
>> whos C
Name Size Bytes Class Attributes
C 2092x31626 529292736 double