Boyut bilgilerini kaybetmeden numpy dizin dilimi


102

Numpy kullanıyorum ve boyut bilgilerini kaybetmeden bir satırı dizine eklemek istiyorum.

import numpy as np
X = np.zeros((100,10))
X.shape        # >> (100, 10)
xslice = X[10,:]
xslice.shape   # >> (10,)  

Bu örnekte xslice artık 1 boyut, ancak (1,10) olmasını istiyorum. R'de, X [10,:, drop = F] kullanırdım. Numpy'de benzer bir şey var mı? Belgelerde bulamadım ve benzer bir sorunun sorulduğunu görmedim.

Teşekkürler!

Yanıtlar:


59

Muhtemelen yapması en kolay x[None, 10, :]veya eşdeğerdir (ancak daha okunaklı) x[np.newaxis, 10, :].

Neden varsayılan olmadığına gelince, şahsen, sürekli olarak tek boyutlu dizilere sahip olmanın çok çabuk sinir bozucu olduğunu görüyorum. Sanırım uyuşuk geliştiriciler de aynı şekilde hissetti.

Ayrıca, yayın dizilerini çok iyi idare eder, bu nedenle dilimin geldiği dizinin boyutunu korumak için genellikle çok az neden vardır. Yaptıysanız, o zaman şöyle şeyler:

a = np.zeros((100,100,10))
b = np.zeros(100,10)
a[0,:,:] = b

ya işe yaramazdı ya da uygulaması çok daha zor olurdu.

(Ya da en azından, dilimleme sırasında boyut bilgilerini düşürmenin arkasındaki uyuşuk geliştiricinin mantığına dair tahminim budur)


6
@Lisa: x[None, 10]Ne istersen yapacak.
naught101

Evet. NoneKestiğiniz ölçülerin yanına kendi sinizi koyun .
Mad Fizikçi

1
Örnekte atamadaki tuple için fazladan parantez eksiktir b; olması gerekir b = np.zeros((100,10)).
Jerzy

Toplamda sadece iki yerine 3 endeks kullanmanın sebebi nedir? Yani X[10,None](kodunuzu örnek olarak kullanarak).
greenoldman

9
" Dizinin boyutunu korumak için genellikle çok az neden vardır " ... Kesinlikle, tamamen ve tamamen matris çarpımını ( np.matmul()veya@ ) mahvedecektir . Sadece bununla yandı.
Jean-François Corbett

93

Başka bir çözüm yapmaktır

X[[10],:]

veya

I = array([10])
X[I,:]

Bir dizinin boyutluluğu, indeksleme bir dizin listesi (veya bir dizi) tarafından gerçekleştirildiğinde korunur. Bu güzel çünkü size boyutu korumak ve sıkıştırmak arasında bir seçim bırakıyor.


2
Bu kopyalar dizi veri
Başına

Bu her zaman böyle değildir. Bakın: x = np.array([[1,2,3,4]]) Eğer onu daha sonra x[[0],[1,2]] dilerseniz tek boyutlu olarak alırsanız array([2, 3]) Benim fikrim sütun veya satır vektörlerini seçerken dilimi basitleştirmek ve sonra kullanmak en iyisidir np.reshape, Yani benim np.reshape(x[0,[1,2]],[1,2])
Alexander

1
diğerleri, sonunda bir noktalı virgülün farkında olun - önemli, X[[10]]şeklinde yorumlanacak X[10]ve şekil daha küçük olacak; benzer şekilde X[[10, 20]] == X[10, 20]ve şekil daha da küçük
Ben Usman

1
Uyarı : Bu indeksleme yöntemini sadece tamsayı indekslemeyle karıştırmayın! Eğer olsaydı aşeklin (10, 20, 30), sonra a[0, :, [0]]şekle sahip olacak (1, 20), değil (20, 1)ikincisi endekslerinde yayınlanır çünkü hiç a[[0], :, [0]]hangi sıklıkla oldukça beklediğiniz ne! Oysa a[0, :, :1]size (20, 1)beklendiği gibi vereceğim . Ayrıca, tek indeksli garip uç durum için yukarıdaki yoruma bakınız. Genel olarak, bu yöntemin çok fazla uç durumu var gibi görünüyor.
Ben Usman

30

Birkaç makul çözüm buldum.

1) kullanım numpy.take(X,[10],0)

2) bu garip indekslemeyi kullanın X[10:11:, :]

İdeal olarak, bu varsayılan olmalıdır. Boyutların neden düştüğünü asla anlamadım. Ama bu hissiz için bir tartışma ...


2
Python listeleri indekslenirken 'boyutlar' bırakılır alist[0]ve dilimlenirken saklanır.
hpaulj

5
Seçenek 2 ( slice(n, n+1)indeksi çıkarmak için yazılabilir n), doğal olarak n-boyutlu duruma uzanan tek seçenek olduğu için kabul edilen cevap olmalıdır.
norok2

Seçenek 2 X[10:11, :], Python 3.7.5'teki gibi yazılabilir gibi görünüyor (yani 11'den sonra fazladan iki nokta üst üste olmadan)
Joe

7

İşte daha çok sevdiğim bir alternatif. Tek bir numara ile indekslemek yerine, bir aralık ile indeksleyin. Yani, kullanın X[10:11,:]. ( 10:1111'i içermediğini unutmayın ).

import numpy as np
X = np.zeros((100,10))
X.shape        # >> (100, 10)
xslice = X[10:11,:]
xslice.shape   # >> (1,10)

Bu, daha fazla boyutla anlamayı da kolaylaştırır, Nonehokkabazlık yapmaz ve hangi eksenin hangi indeksin kullanılacağını bulmaya gerek yoktur . Ayrıca, sadece normal indekslemede kullanacağınız i:i+1herhangi ibiri için , dizi boyutuyla ilgili fazladan defter tutmaya gerek yoktur .

b = np.ones((2, 3, 4))
b.shape # >> (2, 3, 4)
b[1:2,:,:].shape  # >> (1, 3, 4)
b[:, 2:3, :].shape .  # >> (2, 1, 4)


0

Bu, özellikle çalışma zamanında 1 uzunluğunda olabilecek bir dizi ile indeksliyorsanız can sıkıcıdır. Bu durum için np.ix_:

some_array[np.ix_(row_index,column_index)]
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.