NumPy dizisinden belirli satırları ve sütunları seçme


96

Burada yanlış yaptığım aptalca şeyi anlamaya çalışırken çıldırıyorum.

NumPy kullanıyorum ve aralarından seçim yapmak istediğim belirli satır indekslerim ve belirli sütun indekslerim var. İşte sorunumun özü:

import numpy as np

a = np.arange(20).reshape((5,4))
# array([[ 0,  1,  2,  3],
#        [ 4,  5,  6,  7],
#        [ 8,  9, 10, 11],
#        [12, 13, 14, 15],
#        [16, 17, 18, 19]])

# If I select certain rows, it works
print a[[0, 1, 3], :]
# array([[ 0,  1,  2,  3],
#        [ 4,  5,  6,  7],
#        [12, 13, 14, 15]])

# If I select certain rows and a single column, it works
print a[[0, 1, 3], 2]
# array([ 2,  6, 14])

# But if I select certain rows AND certain columns, it fails
print a[[0,1,3], [0,2]]
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# ValueError: shape mismatch: objects cannot be broadcast to a single shape

Bu neden oluyor? Şüphesiz 1., 2. ve 4. satırları ve 1. ve 3. sütunları seçebilmeli miyim? Beklediğim sonuç:

a[[0,1,3], [0,2]] => [[0,  2],
                      [4,  6],
                      [12, 14]]

Etiketli numpy dilimleme bulunabilirliğini artırmak için. (Ayrıca 'dilim' ve 'dilimleme' terimleri düz metinde geçmez, bu terimlerin içine kapatılmış bazı kopyaları kullanabiliriz)
smci

Yanıtlar:


86

Süslü indeksleme, her boyut için tüm indeksleri sağlamanızı gerektirir. Birincisi için 3 endeks ve ikincisi için sadece 2 endeks sağlıyorsunuz, dolayısıyla hata. Bunun gibi bir şey yapmak istiyorsun:

>>> a[[[0, 0], [1, 1], [3, 3]], [[0,2], [0,2], [0, 2]]]
array([[ 0,  2],
       [ 4,  6],
       [12, 14]])

Bu elbette yazmak için bir acı, böylece yayın yapmanın size yardımcı olmasına izin verebilirsiniz:

>>> a[[[0], [1], [3]], [0, 2]]
array([[ 0,  2],
       [ 4,  6],
       [12, 14]])

Listelerle değil dizilerle indekslerseniz bunu yapmak çok daha kolaydır:

>>> row_idx = np.array([0, 1, 3])
>>> col_idx = np.array([0, 2])
>>> a[row_idx[:, None], col_idx]
array([[ 0,  2],
       [ 4,  6],
       [12, 14]])

4
Teşekkürler, bunu yapabileceğini bilmiyordum! Yayıncılık tuhaf ve harika ... İki yıllık uyuşukluğun ardından, hala alışmaya başladım.
Praveen

2
Teşekkürler! Diğer cevaplar seçili matrisi döndürme açısından soruma doğru cevap verirken, bu cevap atama konusuna da değinirken (nasıl a [[0,1,3], [0,2]] = 0 ayarlanır? , Örneğin).
Mike C

1
@Jaime - Daha dün tam olarak önerdiğiniz yayın hilesini yapmak için yerleşik bir tek satırlık yerleşik keşfettim: np.ix_
Praveen

1
Sözdiziminin neden böyle çalıştığına dair birisi bir açıklama sağlayabilir mi? Hem ilk örnekler için hem de üçüncü örnekler için çalışmasının nedeni nedir? Ayrıca, aranan endeksleri kendi listelerine dahil etmek bunu nasıl çözer? Teşekkürler
Aetos

2
Neden satırların iç içe geçmesi gerekiyor ve sütunlar neden değil?
AturSams

86

Toan anlaşılacağı gibi, basit bir hack sadece ilk satırları seçin ve ardından üzerinde sütunları seçmek olacaktır o .

>>> a[[0,1,3], :]            # Returns the rows you want
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [12, 13, 14, 15]])
>>> a[[0,1,3], :][:, [0,2]]  # Selects the columns you want as well
array([[ 0,  2],
       [ 4,  6],
       [12, 14]])

[Düzenle] Yerleşik yöntem: np.ix_

Geçenlerde numpy yapmaya size bir dahili tek astar verdiğini keşfettiler tam @Jaime önerdi, ancak yayın sözdizimi (okunabilirliği eksikliğinden muzdarip) kullanmak zorunda kalmadan. Dokümanlardan:

İx_ one kullanmak çapraz çarpımı indeksleyecek indeks dizilerini hızlı bir şekilde oluşturabilir. a[np.ix_([1,3],[2,5])]diziyi döndürür [[a[1,2] a[1,5]], [a[3,2] a[3,5]]].

Yani bunu şu şekilde kullanıyorsun:

>>> a = np.arange(20).reshape((5,4))
>>> a[np.ix_([0,1,3], [0,2])]
array([[ 0,  2],
       [ 4,  6],
       [12, 14]])

Ve çalışma şekli, Jaime'nin önerdiği şekilde dizileri hizalamaya özen göstermesidir, böylece yayın düzgün bir şekilde gerçekleşir:

>>> np.ix_([0,1,3], [0,2])
(array([[0],
        [1],
        [3]]), array([[0, 2]]))

Ayrıca, MikeC'nin bir yorumda söylediği gibi np.ix_, ilk (ön düzenleme) cevabımın sahip olmadığı bir görüşe geri dönme avantajı vardır. Bu, artık dizinlenmiş diziye atayabileceğiniz anlamına gelir :

>>> a[np.ix_([0,1,3], [0,2])] = -1
>>> a    
array([[-1,  1, -1,  3],
       [-1,  5, -1,  7],
       [ 8,  9, 10, 11],
       [-1, 13, -1, 15],
       [16, 17, 18, 19]])

4
Birkaç testte, np.ix_ilk sütunları ve sonra satırları seçme yönteminden daha hızlı olduğumu da buldum (genellikle tüm satırları ve sütunları yeniden indekslediğiniz 1K-10K boyutlarındaki kare dizileri testlerimde yaklaşık 2 kat daha hızlı).
Nathan

7

KULLANIM:

 >>> a[[0,1,3]][:,[0,2]]
array([[ 0,  2],
   [ 4,  6],
   [12, 14]])

VEYA:

>>> a[[0,1,3],::2]
array([[ 0,  2],
   [ 4,  6],
   [12, 14]])

10
Bu doğru olsa da, neden doğru olduğunu açıklayan biraz daha fazla bilgi yayınlamayı düşünmelisiniz .
ebarr

2

Kullanımı np.ix_en uygun yoldur burada (başkaları tarafından cevap gibi) bunu, ama bunu yapmanın başka ilginç bir yoludur:

>>> rows = [0, 1, 3]
>>> cols = [0, 2]

>>> a[rows].T[cols].T

array([[ 0,  2],
       [ 4,  6],
       [12, 14]])
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.