我有double
的2092x252矩阵,需要创建一个使用for
的{{1}}循环。我们只想说明这个例子bsxfun
。我需要循环完成的是使用每列作为索引运行bsxfun(@minus)
。例如,将第1列指定为索引可获得与第2列:第252列的差异(使用bsxfun(@minus)
)。然后将第2列设置为索引,并使用第3列:252(再次使用bsxfun(@minus)
)获得差异。循环必须继续运行直到bsxfun(@minus)
。
输出将在一个变量而不是251个变量中。总共有31626个数据点。
另外,请你解释一下代码。
答案 0 :(得分:3)
我不确定这是否正是您想要的,因为它会导致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列)和{ {1}}(=所有剩余的列,从第ii个到矩阵的末尾)
bsxfun function说明说:
将逐个元素的二进制操作应用于启用了单例扩展的两个数组
单例扩展是我在这里使用的,bsxfun看到两个输入是一列和一个具有相同大小列的矩阵,并将列扩展为与矩阵相同的大小(=单一扩展(行维度得到)扩大))
因此,如果您希望相互减去行,您只需提供一行和以前相同的矩阵,它也会知道该怎么做,即沿着列维扩展行向量: / p>
data(:,ii+1:end)
如您所见,所有矩阵的索引切换位置: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)
。
在循环的每个步骤中使用单元格作为结果矩阵将允许更容易地访问结果,但由于您希望将结果放在一个变量中(矩阵我假设),我对这些结果进行了评论。
关于预分配:http://www.mathworks.nl/help/techdoc/matlab_prog/f8-784135.html
A(j,i)
是索引,这是最棘手的:
当ii = 1时,您要插入251列:输出变量
中的第1列和第251列
ii = 2 - >输出中的250列,列252-> 501
ii = 3 - >输出中的249列,列502-> 750
ii = 4 =>输出
中的248列,列751-> 999
等
c(:,kk+(1:N-ii));
kk=kk+N-ii
基本上是这样做的:为kk+(1:N-ii)
的输出选择合适的列
变量bsxfun
是已保存到输出变量kk
中的列数,因此很明显它从零开始。如果您将其更改为其他值,例如c
,则kk_init
的第一个kk_init
列将保持为空,结果c
矩阵将包含c
列N*(N-1)/2+kk_init
。
答案 1 :(得分:1)
为了避免跟踪索引,您可以计算并将结果存储在单元格数组中,然后将所有单元格连接成一个矩阵:
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