2013-10-01 17 views
16

Supponiamo che io sonoTrova indice in cui gli elementi cambiano valore NumPy

>>> v 
array([1, 1, 1, 1, 1, 2, 2, 2, 3, 4, 3, 4, 3, 4, 3, 4, 5, 5, 5]) 

C'è un modo NumPy efficace per trovare l'indice in cui il valore cambia? Per esempio, vorrei qualche risultato come,

>>> index_of_changed_values(v) 
[0, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16] 

Se questo non è possibile con un po 'di routine NumPy, che cosa è un modo veloce per farlo in Python? Sarebbe anche utile che mi riferissi ad alcuni buoni tutorial numpy poiché sono un principiante insensibile.

risposta

28

È possibile ottenere questa funzionalità in numpy confrontando ciascun elemento con il suo vicino;

v[:-1] != v[1:] 


array([False, False, False, False, True, False, False, True, True, 
    True, True, True, True, True, True, True, False, False], dtype=bool) 

per ottenere gli indici si utilizza il "dove" la funzione

np.where(v[:-1] != v[1:])[0] 

array([ 4, 7, 8, 9, 10, 11, 12, 13, 14, 15]) 

Da qui si può anteporre il primo elemento e aggiungere uno per raggiungere lo stesso schema di indicizzazione che hai nella tua domanda.

+0

questo funziona perfettamente grazie. Ottima spiegazione anche. – liang

+3

@kith Così semplice, così perfetto, così OMG! –

-1

Forse è perché Python 3.5 ma i codici di cui sopra non ha funzionato per me.

Sembra che v[:-1] != v[1:] non restituisca un iterable ma un singolo bool.

mi si avvicinò con seguente lista di comprensione utilizzando zip e enumerate

[ i for i, (x, y) in enumerate(zip(v[:-1],v[1:])) if x!=y] 

qualcuno in cerca di soluzione in py3.5 potrebbe rivelarsi utile!

+0

sopra il codice usato numpy – ash

+0

@ash: intendevo che 'v [: - 1]! = V [1:]' non ha restituito * array * (o più in generale * array-like-structure *) di 'bools' che a sua volta non ha funzionato con 'numpy.where' in * python 3.5 *. E la risposta era rivolta a persone che sarebbero venute a questa domanda e avrebbero usato python 3.5. E sì, so che il codice sopra utilizza numpy e questo no. – cipher

+1

che è bc devono essere array numpy non liste python – ash

-1

Simile a @kith risposta, ma richiede meno massaggio del risultato:

np.where(np.roll(v,1)!=v)[0] 

Non c'è bisogno di anteporre 0 o aggiungere 1. Esempio:

>>> v=np.array([1, 1, 1, 2, 2, 3, 3, 4, 4, 4]) 
>>> np.where(np.roll(v,1)!=v)[0] 
array([0, 3, 5, 7]) 

EDIT: come accennato @Praveen , questo fallisce quando l'ultimo e il primo elemento sono uguali.

+0

Questo non funzionerà se l'array assomiglia a '[1, 1, 2, 2, 1, 1, 1]'. Ad esempio, il primo e l'ultimo valore sono gli stessi, quindi non otterrai l'indice '0' come ti aspetti ... – Praveen

Problemi correlati