Ist es möglich, mehreren Variablen auf einmal ein einzelnes Numpy-Objekt zuzuweisen?

Zum Beispiel habe ich viele Variablen, die ich mit np.zeros((2,), dtype=np.object) initiieren möchte

Ich dachte an a,b,c = np.zeros((2,), dtype=np.object), bekam aber ein ValueError. a=b=c=np.zeros((2,), dtype=np.object) funktioniert auch nicht, denn wenn ich eine Variable ändere, ändern sich auch die anderen.

Mit drei Variablen wie im obigen Beispiel ist es kein Problem, dies manuell zu tun, aber wenn ich Dutzende habe, wäre es praktisch, dies effizienter tun zu können.

EDIT - Ein konkreteres Beispiel wäre:

a = np.zeros((2,),dtype=np.object)
b = np.zeros((2,),dtype=np.object)
c = np.zeros((2,),dtype=np.object)


a[0] = pd.Series(data=np.random.rand(10))
a[1] = pd.Series(data=np.random.rand(5))

b[0] = 'text1'
b[1] = 'text2'

c[0] = [0,0,0,0,0,0,0,0,0]
c[1] = [1,1,1,1,1]

data = {'a':a, 'b':b, 'c':c}

sio.savemat('test.mat',{'data':data})
0
HappyPy 21 Nov. 2013 im 23:49

4 Antworten

Beste Antwort

Eine gute Möglichkeit, mehrere Arrays zu erstellen, besteht darin, die Anzahl der gewünschten Ausgabearrays als erste Dimension (axis 0) hinzuzufügen. Wenn Sie also drei Arrays der Länge zwei möchten, die mit Nullen des Objekts dtype gefüllt sind, können Sie dies tun:

a, b, c = np.zeros((3,2), object)

Dies funktioniert für jedes Array, bei dem das Entpacken von der ersten Achse aus erfolgt. Einige Beispiele:

a, b, c = np.random.rand(3, 4, 5)
a, b  = np.arange(12).reshape(2,-1)

NB.: Dies ist nicht identisch mit dem Tun

a, b, c = [np.zeros((2,), object) for _ in xrange(3)]

Denn in diesem Fall wurde jedes der Arrays separat erstellt und muss nicht unbedingt im Speicher zusammenhängend sein. Wenn Sie das Entpacken eines einzelnen Arrays verwenden, wurde das ursprüngliche Array zunächst als ein einziges zusammenhängendes Array erstellt, und die neuen Arrays sind nur Ansichten des ursprünglichen Arrays. Sie haben das ursprüngliche Array nicht gespeichert , daher kann ich dies in keiner Weise sehen. Wenn Sie es jedoch gespeichert und dann aufgeteilt haben, werden die gemeinsam genutzten Daten angezeigt:

In [96]: orig = np.zeros((3,2), dtype=np.object)

In [97]: a, b, c = orig

In [98]: orig
Out[98]: 
array([[0, 0],
       [0, 0],
       [0, 0]], dtype=object)

In [99]: a
Out[99]: array([0, 0], dtype=object)

In [100]: a[0] = 9

In [101]: a
Out[101]: array([9, 0], dtype=object)

In [102]: orig
Out[102]: 
array([[9, 0],
       [0, 0],
       [0, 0]], dtype=object)

Aber ohne dass das orig Array gespeichert / an anderer Stelle referenziert wird, kann ich nicht sehen, dass dies ein Problem ist. Der einzige Weg, um den Unterschied zu erkennen, besteht darin, die Flags zu überprüfen:

In [103]: a, b, c = np.zeros((3,2), dtype=np.object)

In [104]: a.flags.owndata
Out[104]: False

In [105]: a, b, c = [np.zeros((2,), dtype=np.object) for _ in xrange(3)]

In [106]: a.flags.owndata
Out[106]: True
1
askewchan 22 Nov. 2013 im 20:03

Das Folgende ist absolut nicht zu empfehlen, aber trotzdem cool

locals().update({
    'x%d' % i : np.zeros((2,), dtype=np.object)
    for i in range(3)
})
print x2
=> array([0, 0], dtype=object)

Aber mach es auch nicht. Verwenden Sie stattdessen eine Liste (zum Beispiel).

0
shx2 21 Nov. 2013 im 19:56

Verwenden Sie ein Listenverständnis:

>>> a, b, c = [np.zeros((2,), dtype=np.object) for _ in xrange(3)]
>>> [id(x) for x in (a,b,c)]      
[172542064, 171775688, 168893512] #Different objects

Wenn Sie Dutzende solcher Variablen hinzufügen möchten, verwenden Sie besser ein Wörterbuch:

>>> my_vars = {x:np.zeros((2,), dtype=np.object) for x in 'abcdef'}
>>> my_vars
{'a': array([0, 0], dtype=object), 'c': array([0, 0], dtype=object), 'b': array([0, 0], dtype=object), 'e': array([0, 0], dtype=object), 'd': array([0, 0], dtype=object), 'f': array([0, 0], dtype=object)}
5
Ashwini Chaudhary 21 Nov. 2013 im 19:51

In Ihrem eigentlichen Code gibt es keinen Grund, diese Variablen zu haben, nur damit Sie sie alle in ein Diktat einfügen können. Und es gibt auch keinen Grund, die Werte zunächst auf gleiche Arrays zu initialisieren, damit Sie sie dann zu den tatsächlich gewünschten Arrays mutieren können. Wenn Sie alles auf offensichtliche Weise schreiben, tritt das Problem, das Sie lösen möchten, nicht einmal auf:

data = {}
data['a'] = np.array([pd.Series(data=np.random.rand(10)),
                      pd.Series(data=np.random.rand(5))])
data['b'] = np.array(['text1', 'text2'])
data['c'] = np.array([[0,0,0,0,0,0,0,0,0], [1,1,1,1,1]])
sio.savemat('test.mat',{'data':data})

Wenn Sie der Meinung sind, dass Sie die Arrays vorab erstellen und dann mutieren müssen, um sicherzustellen, dass Sie die gewünschten Ergebnisse erhalten, wie Sie in den Kommentaren behaupten, führen Sie zunächst einfach diesen Code aus und Sie werden sehen, dass Sie drei 1D-Objekte erhalten Arrays, keine 2D-Arrays von etwas anderem. Wenn Sie jedoch nicht wissen, wie Sie das selbst bestimmen können, und es nicht einfach ausprobieren und testen möchten, können Sie das dtype immer explizit angeben (entweder als object oder als Komplex Typ), um es zu erzwingen.

Selbst wenn Sie die Arrays vorab erstellen müssten (was Sie wiederum nicht tun), gibt es keinen Grund, Dutzende separater Variablen zu erstellen und sie dann in eine zu setzen nachträglich diktieren. Mit anderen Worten, machen Sie einfach Folgendes:

arrays = np.zeros((3,2), dtype=np.object)
data = dict(zip(string.ascii_lowercase, arrays))

Oder wenn Sie aus irgendeinem Grund wirklich völlig separate Arrays möchten, anstatt sie aus einem höherdimensionalen Array herauszuschneiden:

arrays = [np.zeros((2,), dtype=np.object) for _ in range(3)]
data = dict(zip(string.ascii_lowercase, arrays))

Und natürlich können Sie dies alles in einer Funktion zusammenfassen, wenn Sie es mehrmals tun.

1
abarnert 22 Nov. 2013 im 19:36