2017-04-26 3 views
0

J'ai une matrice double 2D constante mat1. J'ai également un tableau de cellules 2D mat2 où chaque cellule contient une matrice double 2D ou 3D. Ces matrices doubles ont le même nombre de lignes et de colonnes que mat1. Je dois multiplier multiplier (. *) mat1 avec chaque tranche de chaque matrice double dans mat2. Le résultat doit être un autre tableau de cellules results de la même taille que mat2, de sorte que les matrices doubles contatining doivent être égales aux matrices doubles de mat2 en termes de taille. Voici mon code pour générer mat1 et mat2 à des fins d'illustration Je me bats au point où la multiplication devrait avoir lieu.MATLAB: Multiplier une matrice 2D avec une matrice 3D dans des tableaux de cellules

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 

Répondre

1

Vous pouvez utiliser bsxfun pour éliminer la nécessité de votre fonction personnalisée multiply2D3D, il fonctionne de la même manière! Code Mise à jour:

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

Cela fonctionne pour les matrices 2D et 3D où le nombre de lignes et est le même Col. dans chacun de vos « tranches », donc il devrait fonctionner dans votre cas.


Vous n'avez pas non plus besoin de boucler séparément les lignes et les colonnes de votre matrice de cellules. Cette boucle a le même nombre d'itérations, mais il est une boucle pas deux, de sorte que le code est un peu plus simple:

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

votre code fonctionne parfaitement. Merci beaucoup. – Andi

+0

Pas de soucis, bravo – Wolfie

0

Une solution que j'ai trouvée est d'externaliser la multiplication d'une 2D avec une matrice 3D dans une fonction. Cependant, je suis curieux de savoir si c'est le moyen le plus efficace de résoudre ce problème?

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

J'avais presque exactement la même réponse que Wolfie mais il me devança.

Quoi qu'il en soit, voici une chemise que je pense est un peu plus sympa:

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

Il utilise arrayfun pour effectuer l'indexation de la boucle et bsxfun pour les multiplications.


Quelques avantages

1) Définition 'UniformOutput' ('un') dans arrayfun renvoie un tableau de cellules si la variable results est également un réseau de cellules et n'a pas besoin d'être initialisés (contrairement à en utilisant des boucles).

2) Les dimensions des index déterminent les dimensions de results à la sortie, afin qu'elles puissent correspondre à ce que vous voulez.

3) La ligne unique peut être utilisée directement comme argument d'entrée d'une fonction.

Inconvénient

1) Can run slower que l'utilisation for boucles comme Wolfie a souligné dans les commentaires.

+1

Bonne réponse/code Jacob, je n'avais pas pensé à utiliser 'arrayfun'! Peut-être vaut la peine de noter un * inconvénient * aussi. Je viens de faire quelques tests, et il semble que l'utilisation de 'arrayfun' est plus lente que de simplement boucler pour une variété de tailles pour les entrées. Voir cette question SO, la meilleure réponse pour qui va dans un peu de profondeur sur les frais généraux et les problèmes de vitesse avec 'arrayfun': http://stackoverflow.com/questions/12522888/arrayfun-can-be-be-significantly-slower-than -an-explicit-loop-in-matlab-pourquoi – Wolfie

+0

@JacobD Votre code fonctionne également parfaitement, cependant, je préfère la solution de Wolfie. Le principal avantage pour moi est que le code est plus facile à lire et à comprendre. Mais c'est mon opinion personnelle. – Andi

+1

@Wolfie Bon point, j'ai oublié d'ajouter quelque chose à propos de la vitesse/overhead avec 'arrayfun'. Pour les petites tailles, ce n'est peut-être pas un problème, mais oui, cela pourrait perdre du temps. J'imagine que la différence de vitesse entre l'utilisation des boucles 'arrayfun' ou' for' dans ce scénario dépend fortement du rapport entre les tailles de matrice 'interne' et 'externe' ('Cells' vs' TimeSeries')). – JacobD