it-swarm.com.de

Unkompliziertes Umformen von 1d in 2d-Array mit 1 Spalte

In numpy variieren die Dimensionen des resultierenden Arrays zur Laufzeit ..__ Zwischen einem 1d-Array und einem 2d-Array mit 1 Spalte gibt es oft Verwirrung .. In einem Fall kann ich die Spalten durchlaufen, im anderen Fall I kann nicht.

Wie lösen Sie dieses Problem auf elegante Weise? Um zu vermeiden, dass mein Code mit if-Anweisungen auf die Dimensionalität überprüft wird, verwende ich diese Funktion:

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

Dies fühlt sich jedoch unelegant und kostspielig an. Gibt es eine bessere Lösung?

13
DevShark

Der einfachste Weg:

ar.reshape(-1, 1)
10
KaaPex

Du könntest es tun -

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

Diese zweite Eingabe in reshape: -1 sorgt für die Anzahl der Elemente für die zweite Achse. Für einen 2D-Eingabefall ändert sich also nichts. Für einen 1D-Eingabefall wird ein 2D-Array erstellt, bei dem alle Elemente auf die erste Achse "verschoben" werden, da ar.shape[0] die Gesamtzahl der Elemente ist.

Probeläufe

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]])
7
Divakar

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. 

3
Luca Citi

Wenn Sie eine Zeile/Spalte mit einer Liste oder einem "laufenden" Slice in Scheiben schneiden, erhalten Sie ein 2D-Array mit einer Zeile/Spalte

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 ]] 

Wenn Sie stattdessen eine einzelne Nummer für die Auswahl der Zeile/Spalte verwenden, wird ein 1D-Array erzeugt, das die Hauptursache Ihres Problems ist:

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

Result:
[ 0.01360395 -0.66592215  0.9440652   0.6437994 ] 
0
Yuval Atzmon

Ich habe nach dtype gefragt, weil Ihr Beispiel rätselhaft ist.

Ich kann ein strukturiertes Array mit 3 Elementen (1d) und 3 Feldern erstellen:

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')])

Ich kann auf ein Feld nach Namen zugreifen (das Hinzufügen von Klammern ändert nichts)

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

wenn ich aber auf 2 Felder zugreife, bekomme ich noch ein 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 sind diese zusätzlichen Klammern von Bedeutung, wenn ich Werte betrachte

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 ein einfaches 2D-Array ist, bekomme ich immer noch keine Form

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 um die Frage zu stellen, ob ein Array 2d ist, unabhängig davon, ob die Indexierung 1d oder 2 zurückgibt, ist Ihre Funktion grundsätzlich in Ordnung

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

Sie können ar.ndim anstelle von len(ar.shape) testen. Auf jeden Fall ist es jedoch 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 gemeinsam genutzten Datenzeiger.

Schauen Sie sich den Code für np.atleast_2d an. es prüft auf 0d und 1d. Im 1d-Fall gibt es result = ary[newaxis,:] zurück. Es fügt zuerst die zusätzliche Achse 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 Art, den if-Test zu umgehen. In kleinen Zeittests ist es schneller, aber wir sprechen von Mikrosekunden, dem Effekt einer Funktionsaufrufschicht.

np.column_stack ist eine weitere Funktion, die bei Bedarf Spalten-Arrays erstellt. Es verwendet:

 if arr.ndim < 2:
        arr = array(arr, copy=False, subok=True, ndmin=2).T
0
hpaulj
y = np.array(12)
y = y.reshape(-1,1)
print(y.shape)

O/P:- (1, 1)
0
Murtaza Chawala