2017-04-26 21 views
0

私は定数2Dの二重行列mat1を持っています。また、2Dセル配列mat2を持っています。すべてのセルには、2Dまたは3Dのダブルマトリックスが含まれています。これらの2つの行列の行数と列数はmat1と同じです。私はmat2の各ダブルマトリックスのすべてのスライスに(。*)mat1を掛けなければなりません。結果は、mat2と同じサイズの別のセル配列resultsである必要があります。これにより、有効な倍精度行列は、サイズの点でmat2の倍精度行列に等しくなければなりません。MATLAB:セル配列内の3D行列を2D行列に掛ける

説明のためにmat1mat2を生成するコードを示します。私は乗算が起こるべきところで苦労しています。

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 

答えて

1

あなたのカスタム関数multiply2D3Dの必要性を取り除くためにbsxfunを使用することができますが、それは同じように動作します!更新されたコード:

results = cell(rowCells,colCells); 
for c = 1:colCells 
    for r = 1:rowCells 
     results{r,c} = bsxfun(@times, mat1, mat2{r,c}); 
    end 
end 

これはrowsとcolsの数があなたの「スライス」のそれぞれで同じである2Dおよび3D行列のために動作しますので、それはあなたのケースで動作するはずです。


また、セル配列の行と列を別々にループする必要もありません。このループは、反復の同じ数を持っていますが、コードがもう少し合理化であるので、それは、一つのループではない2次のとおりです。

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 
+0

コードは完全に機能しています。どうもありがとう。 – Andi

+0

心配なし、歓声 – Wolfie

0

私が思い描いた解決策の1つは、2Dと3Dマトリックスの乗算を関数にアウトソースすることです。しかし、これがこの問題を解決する最も効率的な方法であるかどうかを知りたいのですが、私は興味がありますか?

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 
1

私はWolfieとほぼまったく同じ答えを持っていたが、彼はそれに私を打ちます。

とにかく、ここで私は少し立派だと思う1つのライナーです:

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); 

これは乗算のためのループのインデックスとbsxfunを実行するためにarrayfunを使用していますが。 results変数は、セルアレイとは対照的に(初期化する必要がないので、'UniformOutput''un'arrayfunに戻るセルアレイを指定


いくつかの利点

1)ループを使用して)。

2)インデックスのディメンションによって出力時のresultsのサイズが決まります。

3)関数の入力引数として1行を直接使用できます。Wolfieコメントで指摘したようにforループを使用するよりも

欠点

1)Can run slower

+1

良い答え/コードJacob、私は 'arrayfun'を使うことを考えていませんでした!たぶん*不利益*に気付く価値があるかもしれません。私はちょうどいくつかのテストを行いました。そして、 'arrayfun'を使うことは、入力のためのさまざまなサイズのループ処理よりも遅いようです。このSOの質問を参照してください。その上の答えは、 'arrayfun'のオーバーヘッドとスピードの問題について少し深く入ります:http://stackoverflow.com/questions/12522888/arrayfun-can-be-significantly-slower-than -an-explicit-loop-in-matlab-なぜ – Wolfie

+0

@JacobDあなたのコードも完全に動作していますが、私はWolfieのソリューションを好んでいます。私の主な利点は、コードを読みやすく理解することです。しかし、それは私の個人的な意見です。 – Andi

+1

@Wolfie良い点、 'arrayfun'でスピード/オーバヘッドについて何かを追加するのを忘れました。小さなサイズの場合は問題にならないかもしれませんが、スケールアップすると時間がかかります。私は、このシナリオで 'arrayfun'または' for'ループを使うことの速度の違いは、 '内側'と '外側'の行列の大きさの比率に大きく依存していると思います(CellsとTimeSeriesのOP )。 – JacobD