NumPy çok boyutlu dizinin i sütununa nasıl erişilir?


463

Varsayalım:

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

test[i]Beni anlayan i'inci dizinin (örn hattı [1, 2]). Nasıl erişebilir inci sütunu? (örneğin [1, 3, 5]). Ayrıca, bu pahalı bir işlem olabilir mi?

Yanıtlar:


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

Benzer şekilde,

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

satırlara erişmenizi sağlar. Bu NumPy referansının Bölüm 1.4 (Endeksleme) kapsamındadır . Bu hızlı, en azından benim tecrübelerime göre. Bir döngüdeki her öğeye erişmekten kesinlikle çok daha hızlıdır.


11
Bu bir kopya oluşturmak, bir sütuna bir başvuru almak gibi, referans almak mümkün mü, bu referanstaki herhangi bir değişiklik orijinal diziye yansıtılır.
harmands

@harmands Bu bir kopya oluşturmaz, bir görünüm oluşturur.
rinspy

69

Ayrıca, aynı anda birden fazla sütuna erişmek istiyorsanız şunları yapabilirsiniz:

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

tabii ki bu durumda sadece verilere erişmiyorsunuz ; bir kopyasını geri
gönderiyorsunuz

14
test[:,[0,2]]yalnızca verilere erişir, örneğin test[:, [0,2]] = somethingtesti değiştirir ve başka bir dizi oluşturmaz. Ama copy_test = test[:, [0,2]]aslında dediğin gibi bir kopya oluşturuyor.
Akavall

3
Bu bir kopya oluşturmak, bazı sütunlara bir başvuru almak gibi, referans almak mümkün mü, bu referanstaki herhangi bir değişiklik orijinal diziye yansıtılır?
harmands

@ harman786 sadece değiştirilmiş diziyi eskisine atayabilirsiniz.
Tamoghna Chowdhury

Neden test[:,[0,2]]sadece veriye erişmiyorsunuz test[:, [0, 2]][:, [0, 1]]? Aynı şeyi tekrar yapmanın farklı bir sonucu olduğu çok kasıtsız görünüyor.
mapf

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

Bu komut size bir satır vektörü verir, sadece üzerinde döngü yapmak istiyorsanız, sorun değil, ancak 3xN boyutuna sahip başka bir dizi ile hstack yapmak istiyorsanız,

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

süre

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

size bir sütun vektörü verir, böylece birleştirme veya hstack işlemi yapabilirsiniz.

Örneğin

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

1
indeksleme bir seferde bir sütundan daha fazlasıyla da çalışır, bu nedenle son örnek test [:, [0,1,0]] veya test [:, [aralık (test.shape [1]) + [0]] olabilir ]
lib

5
Satır vektörü yerine bir sütun vektörü almak için [:, [0]] vs [:, 0] belirtmek için +1. Tam aradığım davranış. Ayrıca ek dizinleme notu için lib + 1. Bu cevap en üstteki cevapla birlikte orada olmalıdır.
dhj

1
Bu cevap seçilmelidir
Gusev Slava

22

Ayrıca bir satırı devredebilir ve döndürebilirsiniz:

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

Sütunlara erişmek için en hızlı yolu bulmadan önce bunu bir süredir yapıyorum, bunun daha hızlı, daha yavaş veya sadece testle aynı olup olmadığını merak ediyorum [:, [0]]
José Chamorro


5

Her ne kadar soru cevaplanmış olsa da, bazı nüanslardan bahsetmeme izin verin.

Diyelim ki dizinin ilk sütunuyla ilgileniyorsunuz

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

Diğer cevaplardan zaten bildiğiniz gibi, bunu "satır vektörü" (şekil dizisi) şeklinde almak (3,)için dilimleme kullanırsınız:

arr_c1_ref = arr[:, 1]  # creates a reference to the 1st column of the arr
arr_c1_copy = arr[:, 1].copy()  # creates a copy of the 1st column of the arr

Bir dizinin başka bir dizinin görünümü veya kopyası olup olmadığını kontrol etmek için aşağıdakileri yapabilirsiniz:

arr_c1_ref.base is arr  # True
arr_c1_copy.base is arr  # False

bkz. ndarray.base .

İkisi arasındaki bariz farkın (modifikasyon arr_c1_refetkileyecek arr) yanı sıra, her birini çaprazlamak için bayt adımlarının sayısı farklıdır:

arr_c1_ref.strides[0]  # 8 bytes
arr_c1_copy.strides[0]  # 4 bytes

bkz atılımlar . Bu neden önemli? Şunun Ayerine çok büyük bir diziniz olduğunu düşünün arr:

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

ve ilk sütundaki tüm öğelerin toplamını, yani A_c1_ref.sum()veya toplamını hesaplamak istersiniz A_c1_copy.sum(). Kopyalanan sürümü kullanmak çok daha hızlıdır:

%timeit A_c1_ref.sum()  # ~248 µs
%timeit A_c1_copy.sum()  # ~12.8 µs

Bu, daha önce belirtilen farklı adımlardan kaynaklanmaktadır:

A_c1_ref.strides[0]  # 40000 bytes
A_c1_copy.strides[0]  # 4 bytes

Her ne kadar sütun kopyaları kullanmak daha iyi gibi görünse de, bir kopya yapmak zaman alır ve daha fazla bellek kullanır (bu durumda oluşturmak için yaklaşık 200 µs sürdü) her zaman doğru değildir A_c1_copy. Ancak, ilk etapta kopyaya ihtiyacımız varsa veya dizinin belirli bir sütununda birçok farklı işlem yapmamız gerekiyorsa ve hız için bellekten ödün vermekle sorunuz, o zaman bir kopya yapmak gitmenin yoludur.

Çoğunlukla sütunlarla çalışmakla ilgiliysek, dizimizi satır-büyük ('C') sırası (varsayılan olan) yerine sütun-büyük ('F') düzeninde oluşturmak iyi bir fikir olabilir. ) ekleyin ve kopyalamadan bir sütunu almak için daha önce olduğu gibi dilimlemeyi yapın:

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

Şimdi, toplama işlemini (veya herhangi birini) sütun görünümünde gerçekleştirmek çok daha hızlıdır.

Son olarak, bir diziyi aktarmanın ve satır dilimlemeyi kullanmanın orijinal dizide sütun dilimlemeyi kullanmakla aynı olduğunu not edelim, çünkü transpozisyon sadece orijinal dizinin şeklini ve adımlarını değiştirerek yapılır.

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

3
>>> test
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])

>>> ncol = test.shape[1]
>>> ncol
5L

Ardından 2. - 4. sütunu şu şekilde seçebilirsiniz:

>>> test[0:, 1:(ncol - 1)]
array([[1, 2, 3],
       [6, 7, 8]])
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.