Numpy: Chia mỗi hàng cho một phần tử vector


119

Giả sử tôi có một mảng numpy:

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

và tôi có một "vectơ:" tương ứng

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

Làm thế nào để tôi hoạt động datadọc theo mỗi hàng để trừ hoặc chia để kết quả là:

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

Câu chuyện dài: Làm thế nào để tôi thực hiện một thao tác trên mỗi hàng của mảng 2D với mảng vô hướng 1D tương ứng với mỗi hàng?

Câu trả lời:


181

Bạn đi đây Bạn chỉ cần sử dụng None(hoặc cách khác np.newaxis) kết hợp với phát sóng:

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
đây là tài liệu
sazary


@ user108569 sử dụng phiên bản mới nhất của numpy (1.18.1), Nonevẫn hoạt động tương đương np.newaxis. Tôi không chắc thiết lập của bạn là gì, hoặc vấn đề chính xác bạn đang gặp phải, nhưng câu trả lời vẫn còn hiệu lực.
JoshAdel

11

Như đã đề cập, cắt bằng Nonehoặc với np.newaxeslà một cách tuyệt vời để làm điều này. Một cách khác là sử dụng chuyển tiếp và phát sóng, như trong

(data.T - vector).T

(data.T / vector).T

Đối với mảng chiều cao hơn, bạn có thể muốn sử dụng swapaxesphương thức mảng NumPy hoặc rollaxishàm NumPy . Thực sự có rất nhiều cách để làm điều này.

Để được giải thích đầy đủ hơn về phát sóng, hãy xem http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html


4

Giải pháp của JoshAdel sử dụng np.newaxis để thêm thứ nguyên. Một cách khác là sử dụng định hình lại () để căn chỉnh kích thước để chuẩn bị phát sóng .

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

Thực hiện việc định hình lại () cho phép các kích thước xếp hàng để phát sóng:

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

Lưu ý data/vectorlà ổn, nhưng nó không giúp bạn có câu trả lời mà bạn muốn. Nó chia mỗi cột của array(thay vì mỗi hàng ) cho mỗi phần tử tương ứng của vector. Đó là những gì bạn sẽ nhận được nếu bạn được định hình lại một cách rõ ràng vectorđể 1x3thay thế 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

Cách Pythonic để làm điều này là ...

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

Điều này quan tâm đến việc định hình lại và kết quả cũng ở định dạng dấu phẩy động. Trong các câu trả lời khác, kết quả là ở định dạng số nguyên tròn.

#Note: Không có cột nào trong cả dữ liệu và vectơ phải khớp


Lưu ý: Điều này không làm những gì OP yêu cầu. Kết quả cuối cùng là mảng ([[1., 0.5, 0.33333333], [2., 1., 0.66666667], [3., 1.5, 1.]]). Nó có thể là 'Pythonic' nhưng không chính xác.
Đánh dấu Cramer

1
@MarkCramer Cảm ơn bạn. Tôi đã sửa câu trả lời của mình để cung cấp kết quả đúng.
shantanu pathak

1

Thêm vào câu trả lời của stackoverflowuser2010, trong trường hợp chung, bạn chỉ có thể sử dụng

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

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

data / vector.reshape(-1,1)

Điều này sẽ biến vector của bạn thành một column matrix/vector. Cho phép bạn thực hiện các hoạt động nguyên tố như bạn muốn. Ít nhất với tôi, đây là cách trực quan nhất về nó và vì (trong hầu hết các trường hợp) numpy sẽ chỉ sử dụng một chế độ xem của cùng một bộ nhớ trong để định hình lại nó cũng hiệu quả.


Đây phải là câu trả lời được chấp nhận. Tạo một vectơ cột với .reshape(-1,1) là cách trực quan nhất để sử dụng phát sóng.
Paul Rougieux
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.