2014-06-10 1 views
1

J'utilise la fonction accumarray pour additionner les valeurs dans le vecteur "data" dans les catégories définies par le vecteur "id". Je veux que mon identifiant vectoriel ne soit pas nécessairement trié, et qu'il contient potentiellement des nombres non consécutifs. Je veux aussi finir avec un vecteur de sommes Sij qui a la même taille d'id (plutôt que la même taille d'unique (id)).sortie cumarray étendue pour les données non triées dans matlab

Par exemple

id = [3 2 4 3 2 3]'; 
data = [6 43 3 4 2 5]'; 

En sortie, je veux

Sij = [15 45 3 15 45 15]'; 

J'ai réussi à le faire en créant des ensembles de données et utiliser la fonction join (en utilisant le code suivant), mais je me demandais si il y a un moyen plus efficace (cela fait partie d'une fonction de vraisemblance que je maximise et j'aimerais l'accélérer). Merci!

clear; 
id = [3 2 4 3 2 3]'; 
data = [6 43 3 4 2 5]'; 
indices = [id ones(size(id))]; 
S = accumarray(indices, data); 
DS = dataset((1:size(S))',S); 
DS = DS(DS.S~=0,:); 
DS.Properties.VarNames={'id','S'}; 
C =join(dataset(id),DS); 
Sij = C.S; 

Répondre

2

Vous devez essentiellement répliquer la sortie de accumarray. Le motif de réplication est donné par la troisième sortie du unique:

[~, ~, k] = unique(id); 
s = accumarray(k,data); 
result = s(k); 

Une autre possibilité: utiliser bsxfun pour détecter des valeurs égales de id, puis la multiplication de matrices pour accumuler les valeurs correspondantes de data:

result = bsxfun(@eq, id, id.') * data; 

Testez pour voir quelle approche est la plus rapide pour vous.

+0

Merci beaucoup! J'ai essayé les deux avec un petit ensemble de données et il semble que l'utilisation d'accumarray est beaucoup plus rapide que le bsxfun, bien que bsxfun soit toujours plus rapide que ma méthode (au moins pour mon problème spécifique). – user3026357

Questions connexes