2016-05-31 1 views
4

Disons que j'ai deux (grands) vecteurs a=[0 0 0 0 0] et b=[1 2 3 4 5] de la même taille et un vecteur d'index ind=[1 5 2 1] avec des valeurs dans {1, ..., longueur (a)}. Je voudrais calculerVectorisation ajout de sous-zone

for k = 1:length(ind) 
    a(ind(k)) = a(ind(k)) + b(ind(k)); 
end 
% a = [2 2 0 0 5] 

C'est, je veux ajouter les entrées de b déclarées dans ind-a y compris la multiplicité.

a(ind)=a(ind)+b(ind); 
% a = [1 2 0 0 5] 

est beaucoup plus rapide, bien sûr, mais ignore les indices qui apparaissent plusieurs fois.

Comment puis-je accélérer le code ci-dessus?

+0

Quel est le comportement attendu d'un index qui apparaît plusieurs fois? Souhaitez-vous effectuer l'ajout sur cet index une seule fois? – drorco

+0

Non, je voudrais ajouter l'index aussi souvent qu'il apparaît. Tout comme dans la boucle for-dessus. – Julian

+0

Je ne comprends pas pourquoi a (ind) + b (ind) ignore les indices qui apparaissent plusieurs fois. – GameOfThrows

Répondre

5

Nous pouvons utiliser unique pour identifier les valeurs d'index uniques et utiliser la troisième sortie pour déterminer quels éléments de ind partagent le même index. Nous pouvons ensuite utiliser accumarray pour additionner tous les éléments de b qui partagent le même index. Nous les ajoutons ensuite à la valeur d'origine de a à ces emplacements.

[uniqueinds, ~, inds] = unique(ind); 
a(uniqueinds) = a(uniqueinds) + accumarray(inds, b(ind)).'; 

Si max(inds) == numel(a) cela pourrait être simplifié à ce qui suit depuis accumarray va simplement revenir 0 pour toute entrée manquante dans ind.

a(:) = a(:) + accumarray(ind(:), b(ind)); 
+0

Le résultat auquel je m'attendrais est '' [13 12 9] ''. – Julian

+0

@Julian Désolé à ce sujet. actualisé. – Suever

+0

Cela donne toujours '' [15 14 9] '', je pense. – Julian

3

Une autre approche basée sur accumarray:

a(:) = a(:) + accumarray(ind(:), b(ind(:)), [numel(a) 1]); 

Fonctionnement

accumarray avec deux vecteurs de colonne en tant qu'entrées regroupe les valeurs de la seconde entrée correspondant à la même index dans la premier. La troisième entrée est utilisée ici pour forcer le résultat à avoir la même taille que a, avec des zéros si nécessaire.

+1

Bon point, j'oublie toujours la troisième entrée! – Suever