Numpy kullanarak garip indeksleme


27

(X 2,2,50,100) şeklindeki bir değişkenim var.

Ayrıca, np.array ([0,10,20]) değerine eşit bir y dizim var. X [0,:,:, y] dizinini eklediğimde garip bir şey oluyor.

x = np.full((2,2,50,100),np.nan)
y = np.array([0,10,20])
print(x.shape)
(2,2,50,100)
print(x[:,:,:,y].shape)
(2,2,50,3)
print(x[0,:,:,:].shape)
(2,50,100)
print(x[0,:,:,y].shape)
(3,2,50)

Sonuncusu neden (2,50,3) değil (3,2,50) çıktı?


Numpy'de yeniyim, bu yüzden sorunuza bir cevabım yok. Bunu daha da araştırmak için, sadece 2B veya 3B olan ve herhangi bir eksende en fazla 10 eleman gibi daha küçük bir örnek bulmanızı öneririm.
Code-Apprentice

Yanıtlar:


21

Numpy, dizi şekillerini yayınlamak için gelişmiş dizinlemeyi bu şekilde kullanır. Bir geçirdiğinizde 0ilk dizin için ve yson endeksi için, numpy yayınlayacak 0aynı şekil olması y. Aşağıdaki denklik tutar: x[0,:,:,y] == x[(0, 0, 0),:,:,y]. işte bir örnek

import numpy as np

x = np.arange(120).reshape(2,3,4,5)
y = np.array([0,2,4])

np.equal(x[0,:,:,y], x[(0, 0, 0),:,:,y]).all()
# returns:
True

Şimdi, iki dizin kümesini etkili bir şekilde geçirdiğiniz için, gelişmiş dizin oluşturma API'sını (bu örnekte) dizin çiftleri oluşturmak için kullanıyorsunuz.

x[(0, 0, 0),:,:,y])

# equivalent to
[
  x[0,:,:,y[0]], 
  x[0,:,:,y[1]], 
  x[0,:,:,y[2]]
]

# equivalent to
rows = np.array([0, 0, 0])
cols = y
x[rows,:,:,cols]

# equivalent to
[
  x[r,:,:,c] for r, c in zip(rows, columns)
]

Hangi uzunluğu ile aynı bir ilk boyutu vardır y. Gördüğün bu.

Örnek olarak, sonraki yığında açıklanan 4 boyutlu bir diziye bakın:

x = np.arange(120).reshape(2,3,4,5)
y = np.array([0,2,4])

# x looks like:
array([[[[  0,   1,   2,   3,   4],    -+      =+
         [  5,   6,   7,   8,   9],     Sheet1  |
         [ 10,  11,  12,  13,  14],     |       |
         [ 15,  16,  17,  18,  19]],   -+       |
                                                Workbook1
        [[ 20,  21,  22,  23,  24],    -+       |
         [ 25,  26,  27,  28,  29],     Sheet2  |
         [ 30,  31,  32,  33,  34],     |       |
         [ 35,  36,  37,  38,  39]],   -+       |
                                                |
        [[ 40,  41,  42,  43,  44],    -+       |
         [ 45,  46,  47,  48,  49],     Sheet3  |
         [ 50,  51,  52,  53,  54],     |       |
         [ 55,  56,  57,  58,  59]]],  -+      =+


       [[[ 60,  61,  62,  63,  64],
         [ 65,  66,  67,  68,  69],
         [ 70,  71,  72,  73,  74],
         [ 75,  76,  77,  78,  79]],

        [[ 80,  81,  82,  83,  84],
         [ 85,  86,  87,  88,  89],
         [ 90,  91,  92,  93,  94],
         [ 95,  96,  97,  98,  99]],

        [[100, 101, 102, 103, 104],
         [105, 106, 107, 108, 109],
         [110, 111, 112, 113, 114],
         [115, 116, 117, 118, 119]]]])

x şimdi ne olduğunu göstermek için kullanabileceğimiz, anlaşılması gerçekten kolay bir sıraya sahip ...

İlk boyut 2 Excel Çalışma Kitabına sahip olmak, ikinci boyut her çalışma kitabında 3 sayfaya sahip olmak gibi, üçüncü boyut sayfa başına 4 satıra sahip olmak gibi ve son boyut her satır (veya sayfa başına sütun) için 5 değerdir.

Bu şekilde bakmak, şunu x[0,:,:,0]sormaktır: "ilk çalışma kitabında, her sayfa için, her satır için, bana ilk değeri / sütunu verin."

x[0,:,:,y[0]]
# returns:
array([[ 0,  5, 10, 15],
       [20, 25, 30, 35],
       [40, 45, 50, 55]])

# this is in the same as the first element in:
x[(0,0,0),:,:,y]

Ancak şimdi gelişmiş dizine ekleme ile x[(0,0,0),:,:,y]"ilk çalışma kitabında, her sayfa için, her satır için, bana yth değerini / sütununu verebiliriz . Tamam, şimdi her değeri için yap y"

x[(0,0,0),:,:,y]
# returns:
array([[[ 0,  5, 10, 15],
        [20, 25, 30, 35],
        [40, 45, 50, 55]],

       [[ 2,  7, 12, 17],
        [22, 27, 32, 37],
        [42, 47, 52, 57]],

       [[ 4,  9, 14, 19],
        [24, 29, 34, 39],
        [44, 49, 54, 59]]])

Çıldırdığı yer, numpy'nin dizin dizisinin dış boyutlarıyla eşleşecek şekilde yayın yapmasıdır . Yani yukarıdaki ile aynı işlemi yapmak istiyorsanız, ancak HEM ​​"Excel çalışma kitapları" için, döngü ve bitiştirmek zorunda değilsiniz. Bir diziyi ilk boyuta geçirebilirsiniz, ancak uyumlu bir şekle sahip OLMALIDIR .

Bir tamsayıyı iletmek yayın yapar y.shape == (3,). Bir diziyi ilk dizin olarak iletmek istiyorsanız, dizinin yalnızca son boyutunun uyumlu olması gerekir y.shape. Yani, ilk dizinin son boyutu 3 veya 1 olmalıdır.

ix = np.array([[0], [1]])
x[ix,:,:,y].shape
# each row of ix is broadcast to length 3:
(2, 3, 3, 4)

ix = np.array([[0,0,0], [1,1,1]])
x[ix,:,:,y].shape
# this is identical to above:
(2, 3, 3, 4)

ix = np.array([[0], [1], [0], [1], [0]])
x[ix,:,:,y].shape
# ix is broadcast so each row of ix has 3 columns, the length of y
(5, 3, 3, 4)

Dokümanlarda kısa bir açıklama bulundu: https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#combining-advanced-and-basic-indexing


Düzenle:

Orijinal sorudan, istediğiniz alt dilimin bir astarını almak için şunları kullanabilirsiniz x[0][:,:,y]:

x[0][:,:,y].shape
# returns
(2, 50, 3)

Ancak, bu alt öğelere atamaya çalışıyorsanız , orijinal dizinin paylaşılan bellek görünümüne baktığınızdan çok dikkatli olmalısınız. Aksi takdirde, atama orijinal diziye değil, bir kopyasına yapılır.

Paylaşılan bellek yalnızca dizinizi alt kümesi olarak ayarlamak için bir tamsayı veya dilim kullandığınızda oluşur, yani x[:,0:3,:,:]veya x[0,:,:,1:-1].

np.shares_memory(x, x[0])
# returns:
True

np.shares_memory(x, x[:,:,:,y])
# returns:
False

Hem orijinal sorunuzda hem de yörneğimde bir int veya dilim yok, bu yüzden her zaman orijinalin bir kopyasına atanır.

FAKAT! İçin dizi Çünkü ybir dilim olarak ifade edilebilir, sen CAN aslında aracılığıyla dizinin bir atanabilir görünüm elde:

x[0,:,:,0:21:10].shape
# returns:
(2, 50, 3)

np.shares_memory(x, x[0,:,:,0:21:10])
# returns:
True

# actually assigns to the original array
x[0,:,:,0:21:10] = 100

Burada dilim içinde 0:21:10olacak her dizin kapmak için kullanın range(0,21,10). Biz kullanmak zorunda 21değil 20durdurma noktası sadece olduğu gibi dilim dışındadır, çünkü rangefonksiyonu.

Temel olarak, alt ölçeklendirme ölçütlerinize uyan bir dilim oluşturabilirseniz, atama yapabilirsiniz.


4

Buna denir combining advanced and basic indexing. İçinde combining advanced and basic indexing, numpy önce gelişmiş indekslemedeki indekslemeyi yapar ve sonucu temel indeksleme boyutuna alt / bitirir.

Dokümanlardan örnek:

X.shape (10,20,30,40,50) olsun ve ind_1 ve ind_2'nin şekle (2,3,4) yayınlanabileceğini varsayalım. Sonra x [:, ind_1, ind_2] 'nin şekli (10,2,3,4,40,50) vardır, çünkü X'ten (20,30) şeklindeki altuzay, (2,3,4)' ten gelen altuzay ile değiştirilmiştir. endeksler. Bununla birlikte, x [:, ind_1,:, ind_2] ' nin şekli (2,3,4,10,30,50) vardır, çünkü indeksleme alt alanında bırakılacak kesin bir yer yoktur, bu nedenle başlangıca bağlanır . Alt alanı istediğiniz yere taşımak için .transpose () işlevini kullanmak her zaman mümkündür. Bu örneğin take kullanılarak çoğaltılamayacağını unutmayın.

böylece, üzerinde x[0,:,:,y], 0ve ypeşin indeksleme vardır. Boyut vermek için birlikte yayınlanırlar (3,).

In [239]: np.broadcast(0,y).shape
Out[239]: (3,)

Bu (3,)2. ve 3. boyutun başlangıcını ele almak(3, 2, 50)

1. ve son boyut gerçekten birlikte yayın olduğunu görmek için, değişiklik deneyebilirsiniz 0için [0,1]yayın hatayı görmek için

print(x[[0,1],:,:,y])

Output:
IndexError                                Traceback (most recent call last)
<ipython-input-232-5d10156346f5> in <module>
----> 1 x[[0,1],:,:,y]

IndexError: shape mismatch: indexing arrays could not be broadcast together with
 shapes (2,) (3,)
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.