2017-04-24 9 views
6

Ich habe eine einfache Liste von Elementen und ich versuche, eine structured array daraus zu machen.Erstellen eines strukturierten Arrays aus einer Liste

Diese naive Ansatz versagt:

y = np.array([1,2,3], dtype=[('y', float)]) 
TypeError: expected an object with a buffer interface 

jedes Element in einem Tupel Putting funktioniert:

# Manuel way 
y = np.array([(1,), (2,), (3,)], dtype=[('y', float)]) 
# Comprehension 
y = np.array([tuple((x,)) for x in [1,2,3]], dtype=[('y', float)]) 

Es funktioniert auch, wenn ich ein Array aus der Liste erstellen zuerst:

y = np.array(np.array([1,2,3]), dtype=[('y', float)]) 

Ich bin ein bisschen verwirrt. Wie kommt es, dass letzteres funktioniert, aber numpy konnte nicht Dinge aussortieren, wenn eine einfache Liste zur Verfügung gestellt wird?

Was ist der empfohlene Weg? Die Erstellung dieses Intermediates hat möglicherweise keine großen Auswirkungen auf die Performance, aber ist dies nicht suboptimal?

Ich bin auch überrascht, dass diejenigen, die nicht arbeiten:

# All lists 
y = np.array([[1,], [2,], [3,]], dtype=[('y', float)]) 
TypeError: expected an object with a buffer interface 
# All tuples 
y = np.array(((1,), (2,), (3,)), dtype=[('y', float)]) 
ValueError: size of tuple must match number of fields. 

Ich bin neu strukturierte Arrays und ich erinnere mich nicht numpy Typen dass pingelig über Eingang. Es muss etwas geben, was mir fehlt.

+0

Da Zeilen müssen mit Tupeln zugeordnet werden, da jedes Element eines strukturierten Array a * struct * ist, so gibt es eine Art von Verbindung Datentyp. Die Alternative besteht darin, einen Puffer zu verwenden (weshalb "np.array" funktioniert). –

+0

Dies ist eine Art dokumentiert [hier] (https://docs.scipy.org/doc/numpy/user/basics.rec.html#filling-structured-arrays) –

+0

Und der vorherige Docs-Absatz erwähnt 'Beachten Sie, dass x ist erstellt mit einer Liste von Tupeln. Dieser Eingabestil entspricht dem Anzeigestil. Ich bevorzuge Ihren Listenverständnisansatz. Oder füllen Sie ein vorher zugeordnetes Array Feld für Feld. – hpaulj

Antwort

3

Details wie np.array behandelt verschiedene Eingaben sind im kompilierten Code begraben. Wie die vielen Fragen zum Erstellen von Objekt-Dtyp-Arrays zeigen, kann es kompliziert und verwirrend sein. Das grundlegende Modell besteht darin, ein mehrdimensionales numerisches Array aus einer verschachtelten Liste zu erstellen.

np.array([[1,2,3],[4,5,6]]) 

In strukturierte Arrays Implementierung angenommen Entwickler die tuple als eine Möglichkeit, einen Datensatz aus nur einem weiteren verschachtelten Dimension zu unterscheiden. Dies zeigt sich in der Darstellung eines strukturierten Arrays.

Es ist auch eine Anforderung beim Definieren eines strukturierten Arrays, obwohl die Anforderung list of tuples ist etwas in der Dokumentation begraben.

In [382]: dt=np.dtype([('y',int)]) 
In [383]: np.array(alist,dt) 

TypeError: a bytes-like object is required, not 'int' 

Dies ist meine Version '1.12.0' Fehlermeldung. Es scheint bei dir anders zu sein.

Wie Sie bemerken, ein Listenverständnis kann die Nestliste in eine Liste von Tupeln konvertieren.

In [384]: np.array([tuple(i) for i in alist],dt) 
Out[384]: 
array([(1,), (2,), (3,)], 
     dtype=[('y', '<i4')]) 

Bei der Beantwortung von SO-Fragen ist das der Ansatz, den ich am häufigsten verwende. Entweder das oder iterativ Felder eines vorher zugewiesenen Arrays (normalerweise gibt es viel mehr Datensätze als Felder, so dass Schleife nicht teuer ist).

Es sieht aus wie das Array in einem strukturierten Array Anruf Einwickeln entspricht einen astype Aufruf:

In [385]: np.array(np.array(alist),dt) 
Out[385]: 
array([[(1,)], 
     [(2,)], 
     [(3,)]], 
     dtype=[('y', '<i4')]) 
In [386]: np.array(alist).astype(dt) 
Out[386]: 
array([[(1,)], 
     [(2,)], 
     [(3,)]], 
     dtype=[('y', '<i4')]) 

Aber beachten Sie die Änderung in der Anzahl der Dimensionen. Die Liste der Tupel erzeugte ein (3,) Array. Das astype konvertierte ein (3,1) numerisches Array in ein (3,1) strukturiertes Array.

Ein Teil dessen, was die Tupel sagen np.array ist - setzen Sie die Division zwischen Array-Dimensionen und Datensätze 'hier'.Er interpretiert

[(3,), (1,), (2,)] 
[record, record, record] 

wo die automatische Übersetzung von [[1],[2],[3]] könnte

[[record],[record],[record]] 

produzieren Wenn die dtype numerische (nicht strukturiert) ist, ignoriert es die Unterscheidung zwischen Listen- und Tupel

In [388]: np.array([tuple(i) for i in alist],int) 
Out[388]: 
array([[1], 
     [2], 
     [3]]) 

Aber Wenn der dtype zusammengesetzt ist, haben sich Entwickler dafür entschieden, die Tupelschicht als wichtige Information zu verwenden.


Betrachten sie eine komplexe strukturierte dtype

In [389]: dt1=np.dtype([('y',int,(2,))]) 
In [390]: np.ones((3,), dt1) 
Out[390]: 
array([([1, 1],), ([1, 1],), ([1, 1],)], 
     dtype=[('y', '<i4', (2,))]) 
In [391]: np.array([([1,2],),([3,4],)]) 
Out[391]: 
array([[[1, 2]], 

     [[3, 4]]]) 
In [392]: np.array([([1,2],),([3,4],)], dtype=dt1) 
Out[392]: 
array([([1, 2],), ([3, 4],)], 
     dtype=[('y', '<i4', (2,))]) 

Display (und Eingang) hat Listen innerhalb Tupel aus der Liste. Und das ist nur der Anfang

In [393]: dt1=np.dtype([('x',dt,(2,))]) 
In [394]: dt1 
Out[394]: dtype([('x', [('y', '<i4')], (2,))]) 
In [395]: np.ones((2,),dt1) 
Out[395]: 
array([([(1,), (1,)],), ([(1,), (1,)],)], 
     dtype=[('x', [('y', '<i4')], (2,))]) 

convert list of tuples to structured numpy array

+0

Vielen Dank für diese umfassende Antwort. Es macht jetzt mehr Sinn. Ich war ein wenig überrascht, denn nach meiner bescheidenen Erfahrung war "Ich-bin-ein-Wissenschaftler-ohne-Python-Hintergrund-und-ich-kann-..." einfach, mit wenig Erstaunen, und es scheint Die Manipulation strukturierter Arrays erfordert viel mehr Vorkehrungen und ein besseres Verständnis dessen, was im Inneren passiert. –

Verwandte Themen