Numpy: Her satırı bir vektör öğesine bölün


119

Uyuşmuş bir dizim olduğunu varsayalım:

data = np.array([[1,1,1],[2,2,2],[3,3,3]])

ve karşılık gelen bir "vektörüm var:"

vector = np.array([1,2,3])

dataÇıkarmak veya bölmek için her satırda nasıl işlem yaparım, böylece sonuç şu olur:

sub_result = [[0,0,0], [0,0,0], [0,0,0]]
div_result = [[1,1,1], [1,1,1], [1,1,1]]

Uzun lafın kısası: Bir 2D dizinin her satırında, her satıra karşılık gelen 1 boyutlu bir skaler dizisi ile nasıl işlem yapabilirim?

Yanıtlar:


181

Hadi bakalım. Sadece yayınla birlikte None(veya alternatif olarak np.newaxis) kullanmanız gerekir :

In [6]: data - vector[:,None]
Out[6]:
array([[0, 0, 0],
       [0, 0, 0],
       [0, 0, 0]])

In [7]: data / vector[:,None]
Out[7]:
array([[1, 1, 1],
       [1, 1, 1],
       [1, 1, 1]])

13
işte doktor.
sazary


@ numpy (1.18.1) 'in en son sürümünü kullanan user108569, Noneyine de eşdeğer olarak çalışır np.newaxis. Kurulumunuzun ne olduğundan veya tam olarak yaşadığınız sorunun ne olduğundan emin değilim, ancak yanıt hala geçerli.
JoshAdel

11

Bahsedildiği gibi, birlikte dilimleme Noneveya np.newaxesbunu yapmak için harika bir yoldur. Diğer bir alternatif, transpoze ve yayınlamayı kullanmaktır.

(data.T - vector).T

ve

(data.T / vector).T

Daha yüksek boyutlu diziler için swapaxesNumPy dizilerinin yöntemini veya NumPy rollaxisişlevini kullanmak isteyebilirsiniz . Bunu yapmanın gerçekten birçok yolu var.

Yayınla ilgili daha kapsamlı bir açıklama için bkz. Http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html


4

JoshAdel'in çözümü, boyut eklemek için np.newaxis kullanıyor. Bir alternatif, yayına hazırlanırken boyutları hizalamak için reshape () kullanmaktır .

data = np.array([[1,1,1],[2,2,2],[3,3,3]])
vector = np.array([1,2,3])

data
# array([[1, 1, 1],
#        [2, 2, 2],
#        [3, 3, 3]])
vector
# array([1, 2, 3])

data.shape
# (3, 3)
vector.shape
# (3,)

data / vector.reshape((3,1))
# array([[1, 1, 1],
#        [1, 1, 1],
#        [1, 1, 1]])

Yeniden şekillendirmenin () gerçekleştirilmesi, boyutların yayın için sıralanmasına izin verir:

data:            3 x 3
vector:              3
vector reshaped: 3 x 1

data/vectorTamam olduğunu unutmayın , ancak istediğiniz yanıtı size vermez. Her bölen sütunu içinde array(yerine her sıranın her biri karşılık gelen elemanı ile) vector. Bu açıkça yeniden şekillendirmiştir eğer alacağı ne vectorolmak 1x3yerine 3x1.

data / vector
# array([[1, 0, 0],
#        [2, 1, 0],
#        [3, 1, 1]])
data / vector.reshape((1,3))
# array([[1, 0, 0],
#        [2, 1, 0],
#        [3, 1, 1]])

2

Bunu yapmanın Pythonic yolu ...

np.divide(data.T,vector).T

Bu, yeniden şekillendirme ile ilgilenir ve ayrıca sonuçlar kayan nokta formatındadır. Diğer cevaplarda sonuçlar yuvarlanmış tamsayı biçimindedir.

# NOT: Hem verilerdeki hem de vektördeki sütunların hiçbiri eşleşmemelidir


Not: Bu, OP'nin istediği şeyi yapmaz. Sonuç dizidir ([[1., 0.5, 0.33333333], [2., 1., 0.66666667], [3., 1.5, 1.]]). 'Pythonic' olabilir ama yanlıştır.
Mark Cramer

1
@MarkCramer Teşekkürler. Doğru sonucu sağlamak için cevabımı düzelttim.
shantanu pathak

1

Stackoverflowuser2010 cevabına ek olarak, genel durumda sadece kullanabilirsiniz

data = np.array([[1,1,1],[2,2,2],[3,3,3]])

vector = np.array([1,2,3])

data / vector.reshape(-1,1)

Bu, vektörünüzü bir column matrix/vector. Elementsel işlemleri istediğiniz gibi yapmanıza izin verir. En azından benim için, bu konudaki en sezgisel yol ve çünkü (çoğu durumda) numpy, yeniden şekillendirme için aynı dahili belleğin bir görüntüsünü kullanacak.


Kabul edilen cevap bu olmalıdır. İle bir sütun vektörü oluşturmak .reshape(-1,1) , yayını kullanmanın en sezgisel yoludur.
Paul Rougieux
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.