Hoe toegang krijgen tot de i-de kolom van een NumPy multidimensionale array?

Stel dat ik heb:

test = numpy.array([[1, 2], [3, 4], [5, 6]])

test[i]geeft me deregel van de array (bijv. [1, 2]). Hoe krijg ik toegang tot de dekolom? (bijv. [1, 3, 5]). Zou dit ook een dure operatie zijn?


Antwoord 1, autoriteit 100%

>>> test[:,0]
array([1, 3, 5])

Evenzo,

>>> test[1,:]
array([3, 4])

geeft u toegang tot rijen. Dit wordt behandeld in Sectie 1.4 (Indexering) van de NumPy-referentie. Dit is snel, althans in mijn ervaring. Het is zeker veel sneller dan toegang tot elk element in een lus.


Antwoord 2, autoriteit 10%

En als u meer dan één kolom tegelijk wilt openen, kunt u het volgende doen:

>>> test = np.arange(9).reshape((3,3))
>>> test
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
>>> test[:,[0,2]]
array([[0, 2],
       [3, 5],
       [6, 8]])

Antwoord 3, autoriteit 10%

>>> test[:,0]
array([1, 3, 5])

dit commando geeft je een rijvector, als je er gewoon overheen wilt lopen, is dat prima, maar als je wilt hstacken met een andere array met dimensie 3xN, heb je

ValueError: all the input arrays must have same number of dimensions

terwijl

>>> test[:,[0]]
array([[1],
       [3],
       [5]])

geeft u een kolomvector, zodat u een aaneenschakeling of hstack-bewerking kunt uitvoeren.

bijv.

>>> np.hstack((test, test[:,[0]]))
array([[1, 2, 1],
       [3, 4, 3],
       [5, 6, 5]])

Antwoord 4, autoriteit 3%

U kunt ook een rij transponeren en retourneren:

In [4]: test.T[0]
Out[4]: array([1, 3, 5])

Antwoord 5, autoriteit 2%

Hoewel de vraag is beantwoord, wil ik toch enkele nuances noemen.

Stel dat u geïnteresseerd bent in de eerste kolom van de array

arr = numpy.array([[1, 2],
                   [3, 4],
                   [5, 6]])

Zoals je al weet uit andere antwoorden, gebruik je slicing om het in de vorm van “rijvector” (array of shape (3,)) te krijgen:

arr_col1_view = arr[:, 1]         # creates a view of the 1st column of the arr
arr_col1_copy = arr[:, 1].copy()  # creates a copy of the 1st column of the arr

Om te controleren of een array een view of een kopie van een andere array is, kun je het volgende doen:

arr_col1_view.base is arr  # True
arr_col1_copy.base is arr  # False

zie ndarray.base.

Behalve het duidelijke verschil tussen de twee (het wijzigen van arr_col1_viewheeft invloed op de arr), is het aantal byte-stappen voor het doorlopen van elk ervan verschillend:

arr_col1_view.strides[0]  # 8 bytes
arr_col1_copy.strides[0]  # 4 bytes

zie stappenen dit antwoord.

Waarom is dit belangrijk? Stel je voor dat je een hele grote array Ahebt in plaats van de arr:

A = np.random.randint(2, size=(10000, 10000), dtype='int32')
A_col1_view = A[:, 1] 
A_col1_copy = A[:, 1].copy()

en u wilt de som berekenen van alle elementen van de eerste kolom, d.w.z. A_col1_view.sum()of A_col1_copy.sum(). Het gebruik van de gekopieerde versie is veel sneller:

%timeit A_col1_view.sum()  # ~248 µs
%timeit A_col1_copy.sum()  # ~12.8 µs

Dit komt door het verschillende aantal stappen dat eerder is genoemd:

A_col1_view.strides[0]  # 40000 bytes
A_col1_copy.strides[0]  # 4 bytes

Hoewel het misschien lijkt alsof het gebruik van kolomkopieën beter is, is dit niet altijd waar omdat het maken van een kopie ook tijd kost en meer geheugen kost (in dit geval kostte het me ongeveer 200 µs om de A_col1_copy). Maar als we de kopie in de eerste plaats nodig hadden, of als we veel verschillende bewerkingen op een specifieke kolom van de array moeten doen en we het goed vinden om geheugen op te offeren voor snelheid, dan is het maken van een kopie de juiste keuze.

In het geval dat we voornamelijk met kolommen willen werken, kan het een goed idee zijn om onze array te maken in kolom-hoofdvolgorde (‘F’) in plaats van rij-groot (‘C’) (wat is de standaard), en doe dan het snijden zoals voorheen om een kolom te krijgen zonder deze te kopiëren:

A = np.asfortranarray(A)   # or np.array(A, order='F')
A_col1_view = A[:, 1]
A_col1_view.strides[0]     # 4 bytes
%timeit A_col1_view.sum()  # ~12.6 µs vs ~248 µs

Het uitvoeren van de sombewerking (of een andere) op een kolomweergave is nu net zo snel als het uitvoeren op een kolomkopie.

Laat me ten slotte opmerken dat het transponeren van een array en het gebruik van row-slicing hetzelfde is als het gebruik van column-slicing op de originele array, omdat transponeren wordt gedaan door gewoon de vorm en de stappen van de originele array om te wisselen.

>

A[:, 1].strides[0]    # 40000 bytes
A.T[1, :].strides[0]  # 40000 bytes

Antwoord 6

Om meerdere en onafhankelijke kolommen te krijgen:

> test[:,[0,2]]

u krijgt kolommen 0 en 2


Antwoord 7

>>> test
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])
>>> ncol = test.shape[1]
>>> ncol
5L

Vervolgens kunt u de 2e – 4e kolom op deze manier selecteren:

>>> test[0:, 1:(ncol - 1)]
array([[1, 2, 3],
       [6, 7, 8]])

Antwoord 8

Dit is niet multidimensionaal. Het is een 2-dimensionale array. waar u toegang wilt tot de gewenste kolommen.

test = numpy.array([[1, 2], [3, 4], [5, 6]])
test[:, a:b]  # you can provide index in place of a and b

Other episodes