2016-11-24 6 views
1

Gibt es eine Möglichkeit, eine Python-Liste wie x = ['a','b','c'] mit einem numpy boolean Array zu indizieren? Ich erhalte derzeit den folgenden Fehler: TypeError: only integer arrays with one element can be converted to an indexIndex Python-Liste mit Numpy Boolean Array

+1

In Im Gegensatz zu Arrays können Listen nur mit Skalaren und Slices indiziert werden. Sie müssen etwas wie ein Listenverständnis verwenden, z. [i für i, j in zip (x, Maske) wenn j] '. – hpaulj

+0

@Appolo, können Sie Ihren Code dort anzeigen, wo Sie die Indizierung versuchen? – RomanPerekhrest

+0

@hpaulj was ist, wenn ich 'x [list (mynumpyarr)]' – Apollo

Antwort

3

Indizierung über [] ruft heimlich die __getitem__ Methode des Objekts auf. Für Objekte, die in reinem Python implementiert sind, können Sie diese Methode einfach mit einer Funktion überschreiben, die Ihren Anforderungen entspricht. Listen sind jedoch in C implementiert, so dass es nicht erlaubt ist, list.__getitem__ zu ersetzen. Daher gibt es keinen direkten Weg, um das zu tun, was Sie wünschen.

Sie können jedoch eine NumPy Array machen aus Ihrer Liste und tun dann NumPy Stil boolean Indizierung auf, dass:

import numpy as np 

x = ['a', 'b', 'c'] 

mask = np.array([True, False, True]) 
x_arr = np.asarray(x, dtype=object) 
output = x_arr[mask] # Get items 
x_arr[mask] = ['new', 'values'] # Set items 

Leider np.asarray kann nicht einfach einen Blick auf Ihrer Liste machen, so dass die Liste ist einfach kopiert. Dies bedeutet, dass das Original x unverändert bleibt, wenn den Elementen von x_arr neue Werte zugewiesen werden.

Wenn Sie wirklich die volle Leistung von NumPy booleschen Indizierung auf Listen wollen, müssen Sie eine Funktion schreiben, die dies von Grund auf neu, und Sie können nicht die [] Indexierungssyntax verwenden.

3
In [304]: ['a','b','c'][[2,1,0]] 
--------------------------------------------------------------------------- 
TypeError         Traceback (most recent call last) 
<ipython-input-304-c04b1f0621a3> in <module>() 
----> 1 ['a','b','c'][[2,1,0]] 

TypeError: list indices must be integers or slices, not list 

Liste Verständnis Route

In [306]: [i for i,j in zip(['a','b','c'],[True, False, True]) if j] 
Out[306]: ['a', 'c'] 

Array Route zur Liste

In [308]: np.array(['a','b','c'])[np.array([True, False, True])] 
Out[308]: 
array(['a', 'c'], 
     dtype='<U1') 

zurück:

In [309]: np.array(['a','b','c'])[np.array([True, False, True])].tolist() 
Out[309]: ['a', 'c'] 

aber vorsichtig sein, wenn Sie Ihre Liste Objekte enthält, wie Zahlen gegen oder Zeichenfolgen. Dadurch werden die Verknüpfungen möglicherweise nicht beibehalten.

Das operator Modul hat eine itemgetter Funktion

In [321]: operator.itemgetter(*[2,0,1])(list('abc')) 
Out[321]: ('c', 'a', 'b') 

Aber unter der Decke ist es nur eine Liste Verständnis wie Iterator. Und ich sehe nicht ohne weiteres eine boolesche Version.

3

map(x.__getitem__,np.where(mask)[0])

Oder wenn Sie möchten Liste Verständnis

[x[i] for i in np.where(mask)[0]]

Dies hält Sie über die ganze Liste zu durchlaufen hat, vor allem, wenn mask spärlich ist.

1

Benötigen Sie es, um eine Liste zu sein. Da Sie das Indizierungsverhalten eines numpy Arrays verwenden möchten, wäre es für andere Leute, die Ihren Code lesen, sinnvoller, wenn Sie tatsächlich ein numpy Array verwenden.

Vielleicht versuchen, ein Array mit dtype = 'a' zu verwenden?Zum Beispiel in dem folgenden Code,

x = sp.array(['a', 'b', 'c'], dtype='a') 
print(x) 
print(x=='c') 
print(x[x=='c']). 

Dies wird die folgende Arrays zurückgeben,

['a' 'b' 'c'] 
[False False True] 
['c']. 

Zuordnung funktioniert, wie Sie erwarten,

x[x=='c'] = 'z' 
print(x). 

Dies wird die modifizierte Array zurück ,

['a' 'b' 'z']. 

Die einzige Sorge ist, dass die Elemente des Arrays nicht länger als die zugewiesene Länge sein können. Hier wird es als eine mit dtype = 'a' angegeben. Sie können dtype = 'a5' oder dtype = 'aN' für jede gewünschte Länge verwenden. Alle Elemente des Arrays müssen Zeichenfolgen sein, die kürzer als die maximale Länge sind.

Wenn Sie übergeben eine Zeichenfolge, die zu lang ist, wird es das Ende abhacken, wie im folgenden Beispiel mit dtype Satz ‚a2‘:

x = sp.array(['abc', 'bcd', 'cde'], dtype='a2') 
print(x), 

die gibt,

['ab' 'bc' 'cd'].