我有一个常数2D双矩阵mat1
。我还有一个2D单元阵列mat2
,其中每个单元格包含一个2D或3D双矩阵。这些双矩阵与mat1
具有相同的行数和列数。我需要在mat1
内对每个双矩阵的每个切片乘以(。*)mat2
。结果需要是另一个与results
大小相同的单元格数组mat2
,其中,对于大小而言,对等双矩阵必须等于mat2
的双矩阵。
我的代码用于生成mat1
和mat2
以用于说明目的。我正在努力应该进行乘法运算。
rowCells = 5;
colCells = 3;
rowTimeSeries = 300;
colTimeSeries = 5;
slices = [1;10];
% Create 2D double matrix
mat1 = rand(rowTimeSeries, colTimeSeries);
% Create 2D cell matrix comprisiong 2D and/or 3D double matrices
mat2 = cell(rowCells,colCells);
for c = 1:colCells
for r = 1:rowCells
slice = randsample(slices, 1, true);
mat2{r,c} = rand(rowTimeSeries, colTimeSeries, slice);
end
end
% Multiply (.*) mat1 with mat2 (every slice)
results = cell(rowCells,colCells);
for c = 1:colCells
for r = 1:rowCells
results{r,c} = ... % I am struggling here!!!
end
end
答案 0 :(得分:1)
您可以使用bsxfun
删除对自定义函数multiply2D3D
的需求,它的工作方式类似!更新的代码:
results = cell(rowCells,colCells);
for c = 1:colCells
for r = 1:rowCells
results{r,c} = bsxfun(@times, mat1, mat2{r,c});
end
end
这适用于2D和3D矩阵,其中每个"切片"中的行数和列数相同,因此它适用于您的情况。
您也不需要分别遍历单元格数组的行和列。这个循环具有相同的迭代次数,但它是一个循环而不是两个循环,因此代码更加简化:
results = cell(size(mat2));
for n = 1:numel(mat2) % Loop over every element of mat2. numel(mat2) = rowCells*colCells
results{n} = bsxfun(@times, mat1, mat2{n});
end
答案 1 :(得分:1)
我和Wolfie几乎完全一样的答案,但他打败了我。
无论如何,这是一个我认为稍微好一点的班轮:
nR = rowCells; % Number of Rows
nC = colCells; % Number of Cols
results = arrayfun(@(I) bsxfun(@times, mat1, mat2{I}), reshape(1:nR*nC,[],nC), 'un',0);
这使用arrayfun
执行循环索引,并使用bsxfun
进行乘法。
一些优点
1)在arrayfun
中指定'UniformOutput'
('un'
)会返回一个单元格数组,因此results
变量也是一个单元格数组,不需要初始化(与使用循环相反。
2)索引的尺寸决定了输出中results
的尺寸,因此它们可以匹配您喜欢的尺寸。
3)单行可以直接用作函数的输入参数。
<强>缺点强>
正如Wolfie在评论中指出的那样, 1)Can run slower比使用for
循环。
答案 2 :(得分:0)
我想出的一个解决方案是将带有3D矩阵的2D的乘法外包到函数中。但是,我很想知道这是否是解决这个问题的最有效方法?
rowCells = 5;
colCells = 3;
rowTimeSeries = 300;
colTimeSeries = 5;
slices = [1;10];
% Create 2D double matrix
mat1 = rand(rowTimeSeries, colTimeSeries);
% Create 2D cell matrix comprisiong 2D and/or 3D double matrices
mat2 = cell(rowCells,colCells);
for c = 1:colCells
for r = 1:rowCells
slice = randsample(slices, 1, true);
mat2{r,c} = rand(rowTimeSeries, colTimeSeries, slice);
end
end
% Multiply (.*) mat1 with mat2 (every slice)
results = cell(rowCells,colCells);
for c = 1:colCells
for r = 1:rowCells
results{r,c} = multiply2D3D(mat1, mat2{r,c});
end
end
function vout = multiply2D3D(mat2D, mat3D)
%MULTIPLY2D3D multiplies a 2D double matrix with every slice of a 3D
% double matrix.
%
% INPUTs:
% mat2D:
% 2D double matrix
%
% mat3D:
% 3D double matrix where the third dimension is equal or greater than 1.
%
% OUTPUT:
% vout:
% 3D double matrix with the same size as mat3D. Every slice in vout
% is the result of a multiplication of mat2D with every individual slice
% of mat3D.
[rows, cols, slices] = size(mat3D);
vout = zeros(rows, cols, slices);
for s = 1 : slices
vout(:,:,s) = mat2D .* mat3D(:,:,s);
end
end