2016-03-15 8 views
9

In numpy variieren die Dimensionen des resultierenden Arrays zur Laufzeit. Es gibt häufig eine Verwechslung zwischen einem 1d-Array und einem 2d-Array mit 1 Spalte. In einem Fall kann ich über die Spalten iterieren, im anderen Fall kann ich nicht.Numpy formt 1d zu 2d Array mit 1 Spalte

Wie lösen Sie elegant dieses Problem? meinen Code Littering Um zu vermeiden, mit if Aussagen für die Dimensionalität Überprüfung, verwende ich diese Funktion:

def reshape_to_vect(ar): 
    if len(ar.shape) == 1: 
     return ar.reshape(ar.shape[0],1) 
    return ar 

aber das fühlt sich unelegant und teuer. Gibt es eine bessere Lösung?

+0

Was ist der 'dtype'? Sieht "strukturiert" aus. – hpaulj

+0

Es ist irrelevant, ich habe das nur als ein Beispiel dafür verwendet, wie ich mit 1d oder 2d Array enden könnte. Meine Frage ist, wie man elegant 1d zu 2D-Array systematisch konvertiert. – DevShark

Antwort

7

Sie könnten tun -

ar.reshape(ar.shape[0],-1) 

Das zweite Eingang zu reshape: -1 Pflege der Anzahl der Elemente für die zweite Achse stattfindet. Somit ändert sich für einen 2D Eingabefall nichts. Für einen 1D Eingabefall erstellt er ein 2D Array mit allen Elementen, die wegen ar.shape[0], die die Gesamtzahl der Elemente war, auf die erste Achse "geschoben" werden.

Probe läuft

1D Fall:

In [87]: ar 
Out[87]: array([ 0.80203158, 0.25762844, 0.67039516, 0.31021513, 0.80701097]) 

In [88]: ar.reshape(ar.shape[0],-1) 
Out[88]: 
array([[ 0.80203158], 
     [ 0.25762844], 
     [ 0.67039516], 
     [ 0.31021513], 
     [ 0.80701097]]) 

2D-Fall:

In [82]: ar 
Out[82]: 
array([[ 0.37684126, 0.16973899, 0.82157815, 0.38958523], 
     [ 0.39728524, 0.03952238, 0.04153052, 0.82009233], 
     [ 0.38748174, 0.51377738, 0.40365096, 0.74823535]]) 

In [83]: ar.reshape(ar.shape[0],-1) 
Out[83]: 
array([[ 0.37684126, 0.16973899, 0.82157815, 0.38958523], 
     [ 0.39728524, 0.03952238, 0.04153052, 0.82009233], 
     [ 0.38748174, 0.51377738, 0.40365096, 0.74823535]]) 
+1

Eine Variante dieser Antwort ist: 'x = np.reshape (x, (len (x), - 1))', die auch den Fall behandelt, wenn die Eingabe eine 1d oder 2d Liste ist. –

+0

@LucaCiti machen dies eine separate Antwort, so kann ich es abstimmen. –

+0

Fertig. Danke für deine Empfehlung. –

0

Ich fragte nach dtype weil Ihr Beispiel rätselhaft ist.

I kann ein strukturiertes Array bilden mit 3 Elementen (1d) und 3 Felder:

In [1]: A = np.ones((3,), dtype='i,i,i') 
In [2]: A 
Out[2]: 
array([(1, 1, 1), (1, 1, 1), (1, 1, 1)], 
     dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4')]) 

I nach Name ein Feld zugreifen kann (Hinzufügen von Klammern Dinge nicht ändert)

In [3]: A['f0'].shape 
Out[3]: (3,) 

aber wenn ich zwei Felder zugreifen, bekomme ich noch einen 1D-Array

In [4]: A[['f0','f1']].shape 
Out[4]: (3,) 
In [5]: A[['f0','f1']] 
Out[5]: 
array([(1, 1), (1, 1), (1, 1)], 
     dtype=[('f0', '<i4'), ('f1', '<i4')]) 

Eigentlich diese zusätzlichen Klammern keine Rolle, ob ich loo k bei Werten

In [22]: A['f0'] 
Out[22]: array([1, 1, 1], dtype=int32) 
In [23]: A[['f0']] 
Out[23]: 
array([(1,), (1,), (1,)], 
     dtype=[('f0', '<i4')]) 

Wenn das Array eine einfache 2d ist, habe ich noch nicht bekommen, Ihre Formen

In [24]: A=np.ones((3,3),int) 
In [25]: A[0].shape 
Out[25]: (3,) 
In [26]: A[[0]].shape 
Out[26]: (1, 3) 
In [27]: A[[0,1]].shape 
Out[27]: (2, 3) 

Aber was Frage zu machen, dass ein Array 2d, unabhängig davon, ob die Indizierung kehrt 1d oder 2, Ihre Funktion ist im Grunde ok

def reshape_to_vect(ar): 
    if len(ar.shape) == 1: 
     return ar.reshape(ar.shape[0],1) 
    return ar 

Sie testen konnte ar.ndim statt len(ar.shape). Aber so oder so ist es nicht teuer - das heißt, die Ausführungszeit ist minimal - keine großen Array-Operationen. reshape kopiert keine Daten (es sei denn, Ihre Schritte sind seltsam), es sind also nur die Kosten für die Erstellung eines neuen Array-Objekts mit einem gemeinsamen Datenzeiger.

Sehen Sie sich den Code für np.atleast_2d an; es testet für 0d und 1d. Im Fall 1d gibt es result = ary[newaxis,:] zurück. Es fügt die zusätzliche Achse zuerst hinzu, die natürlichere numpy Position zum Hinzufügen einer Achse. Sie fügen es am Ende hinzu.

ar.reshape(ar.shape[0],-1) ist eine clevere Möglichkeit, den if Test zu umgehen. Bei kleinen Timing-Tests geht es schneller, aber wir reden über Mikrosekunden, den Effekt einer Funktionsaufrufschicht.

np.column_stack ist eine weitere Funktion, die bei Bedarf Spaltenarrays erstellt. Es verwendet:

if arr.ndim < 2: 
     arr = array(arr, copy=False, subok=True, ndmin=2).T 
+0

Ok, ich habe das Beispiel entfernt. Ich habe versucht, ein konkretes Beispiel zu geben, aber wenn es verwirrend ist, ist es besser, es nicht zu haben. – DevShark

0

die Notwendigkeit zu vermeiden, in erster Linie neu zu gestalten, wenn Sie eine Zeile/Spalte mit einer Liste in Scheiben schneiden, oder ein „running“ in Scheiben schneidet, werden Sie einen 2D-Array mit einer Zeile/Spalte erhalten

import numpy as np 
x = np.array(np.random.normal(size=(4,4))) 
print x, '\n' 

Result: 
[[ 0.01360395 1.12130368 0.95429414 0.56827029] 
[-0.66592215 1.04852182 0.20588886 0.37623406] 
[ 0.9440652 0.69157556 0.8252977 -0.53993904] 
[ 0.6437994 0.32704783 0.52523173 0.8320762 ]] 

y = x[:,[0]] 
print y, 'col vector \n' 
Result: 
[[ 0.01360395] 
[-0.66592215] 
[ 0.9440652 ] 
[ 0.6437994 ]] col vector 


y = x[[0],:] 
print y, 'row vector \n' 

Result: 
[[ 0.01360395 1.12130368 0.95429414 0.56827029]] row vector 

# Slice with "running" index on a column 
y = x[:,0:1] 
print y, '\n' 

Result: 
[[ 0.01360395] 
[-0.66592215] 
[ 0.9440652 ] 
[ 0.6437994 ]] 

Stattdessen, wenn Sie die Zeile/Spalte für die Wahl einer einzigen Nummer verwenden, wird es in einem 1D-Array führen, was die Ursache für das Problem ist:

y = x[:,0] 
print y, '\n' 

Result: 
[ 0.01360395 -0.66592215 0.9440652 0.6437994 ] 
2

Eine Variante der Antwort von divakar ist: x = np.reshape(x, (len(x),-1)), die auch den Fall behandelt, wenn die Eingabe eine 1D oder 2D Liste ist.