2015-01-13 15 views
5

Desidero assegnare un valore numerico cumulativo per le esecuzioni sequenziali in un vettore binario. Quello che ho èAssegna il conteggio sequenziale per le corse numeriche

x = [0 0 0 1 1 0 1 1 1 0 1 0 0 0 0 0 0], 

e quello che vorrei è

y = [1 2 3 1 2 1 1 2 3 1 1 1 2 3 4 5 6]. 

La soluzione con somma/cumSum/unico/trovare gamma di funzioni me allude. Qualsiasi aiuto sarebbe molto apprezzato.

risposta

6

Ecco un modo:

a = arrayfun(@(x)(1:x), diff(find([1,diff(x),1])), 'uni', 0); 
[a{:}] 

L'idea è quella di generare un elenco dei 'tirature', vale a dire [3,2,1,3,1,1,6] nel tuo caso, poi basta concatenare un gruppo di vettori che contano ad ogni valore in tale elenco , ovvero cat(2, 1:3, 1:2, 1:1, 1:3.... Io uso arrayfun come collegamento per riapplicare l'operatore : e quindi utilizzare l'elenco separato da virgole che {:} restituisce come collegamento per la concatenazione.

+0

Bella one-liner, in particolare con il trucco su ':' – Bentoy13

+0

Beh macchiato sull'applicazione di '' @ (x) 1: x'' su RunLength it codifica! – Nras

+0

wow. grande! Le tue liners sono così belle (e complesse) a volte mi danno il mal di testa! Bel lavoro. –

6

(Non è un one-liner, ahimè ...):

F = find(diff(x))+1; 
y = ones(size(x)); 
y(F) = y(F)-diff([1,F]); 
y = cumsum(y); 

primo luogo, trovare tutte le posizioni in x dove c'è un cambiamento; quindi costruisci un vettore di 1 dove devi sottrarre la lunghezza di ogni segmento continuo. Alla fine, prendi il cumsum di esso.

+0

Questo è un approccio intelligente! – Dan

+0

Avevo anche i soliti sospetti '' find'', '' diff'' e soprattutto '' cumsum'' nella mia mente quando leggevo la domanda. Questo sembrerebbe molto simile al mio (ancora inesistente) approccio. – Nras

+0

Questo è il tipo di soluzione che avevo in mente inizialmente - ma non riuscivo a lavorare. Molte grazie @ Bentoy13. –

1

Creare una matrice sparse tale che ogni corsa è su una colonna diversa, e poi fare la somma cumulativa:

t = sparse(1:numel(x), cumsum([1 diff(x)~=0]), 1); 
y = nonzeros(cumsum(t).*t).'; 

Utilizzare accumarray con una funzione personalizzata per generare ogni aumento modello in una cella diversa , e poi concatenare tutte le cellule:

y = accumarray(cumsum([1 diff(x)~=0]).', 1, [], @(x) {1:numel(x).'}); 
y = [y{:}]; 
+0

una soluzione alternativa che non avrei mai considerato. –

Problemi correlati