2016-01-28 3 views
3

J'ai le morceau de code suivant qui est assez lent pour calculer les centiles d'un ensemble de données ("DATA"), parce que les matrices d'entrée sont grandes ("Data" est environ 500.000 de long avec 10080 valeurs uniques attribuées à partir des "Indices").Améliorer le code/supprimer for-loop lors de l'utilisation accumarray MATLAB

Existe-t-il une possibilité/des suggestions pour rendre ce morceau de code plus efficace? Par exemple, pourrais-je en quelque sorte omettre la boucle for?

k = 1; 
for i = 0:0.5:100; % in 0.5 fractile-steps 
    FRACTILE(:,k) = accumarray(Indices,Data,[], @(x) prctile(x,i)); 
    k = k+1; 
end 
+0

Juste comme une note: 'accumarray' est de toute façon un wrapper pour une boucle. – Adriaan

+0

Fractile semble être une matrice, qu'est-ce que vous essayez réellement de faire? Habituellement, si vous voulez vous débarrasser d'une boucle for, vous pouvez essayer de faire une opération matricielle, quelque chose que matlab est assez bon (mais gardez à l'esprit les limites de la mémoire) –

+0

Oui en effet, c'est une matrice. Je stocke les résultats de centiles individuels (0: 0,5: 100) pour chacun des indices 10080 uniques. – Jonas

Répondre

7

Appel prctile encore et encore avec les mêmes données sont la cause de vos problèmes de performances. Appelez une fois pour chaque ensemble de données:

FRACTILE=cell2mat(accumarray(Indices,Data,[], @(x) {prctile(x,[0:0.5:100])})); 

Laisser prctile évaluer vos 201 percentiles dans un appel coûte à peu près autant de temps de calcul que deux itérations de votre code d'origine. D'abord parce que prctile est plus rapide de cette façon et d'autre part parce que accumarray est appelée seulement une fois maintenant.

+0

Merci beaucoup, c'était exactement ce que je cherchais. Facile à comprendre et beaucoup plus rapide! – Jonas