Cách trả về 0 với số chia cho 0


100

Tôi đang cố thực hiện phép chia khôn ngoan phần tử trong python, nhưng nếu gặp số 0, tôi cần thương số chỉ bằng 0.

Ví dụ:

array1 = np.array([0, 1, 2])
array2 = np.array([0, 1, 1])

array1 / array2 # should be np.array([0, 1, 2])

Tôi luôn có thể chỉ sử dụng vòng lặp for thông qua dữ liệu của mình, nhưng để thực sự tận dụng tối ưu hóa của numpy, tôi cần hàm chia để trả về 0 khi chia cho 0 lỗi thay vì bỏ qua lỗi.

Trừ khi tôi thiếu thứ gì đó, có vẻ như numpy.seterr () không thể trả về giá trị khi có lỗi. Có ai có bất kỳ đề xuất nào khác về cách tôi có thể tận dụng tốt nhất từ ​​numpy trong khi đặt lỗi chia cho 0 của riêng tôi xử lý lỗi không?


Trong phiên bản python của tôi (Python 2.7.11 | Continuum Analytics, Inc.), đó chính xác là đầu ra mà bạn nhận được. Với một cảnh báo.
Ramon Martinez

Câu trả lời đúng ngắn gọn nhất là stackoverflow.com/a/37977222/2116338
mrplants

Câu trả lời:


181

Trong numpy v1.7 +, bạn có thể tận dụng tùy chọn "ở đâu" cho các chức năng . Bạn có thể làm mọi việc trong một dòng và bạn không phải đối phó với trình quản lý ngữ cảnh sai lầm.

>>> a = np.array([-1, 0, 1, 2, 3], dtype=float)
>>> b = np.array([ 0, 0, 0, 2, 2], dtype=float)

# If you don't pass `out` the indices where (b == 0) will be uninitialized!
>>> c = np.divide(a, b, out=np.zeros_like(a), where=b!=0)
>>> print(c)
[ 0.   0.   0.   1.   1.5]

Trong trường hợp này, nó thực hiện phép tính chia ở bất kỳ đâu 'trong đó' b không bằng 0. Khi b bằng 0, thì nó vẫn không thay đổi so với bất kỳ giá trị nào bạn đã cho nó ban đầu trong đối số 'out'.


3
Nếu avà / hoặc bcó thể là số nguyên mảng, sau đó nó được các khái niệm tương tự, bạn chỉ cần thiết lập một cách rõ ràng các loại đầu ra chính xác:c = np.divide(a, b, out=np.zeros(a.shape, dtype=float), where=b!=0)
DStauffman

out=np.zeros_like(a)rất quan trọng, như đã nêu trong dòng bình luận.
Jonatan Öström

1
Nếu tôi sử dụng np.divide(a, b, out=np.zeros_like(a), where=b!=0), tôi nhận được lỗi Assigning to function call which doesn't return. Điều kỳ lạ là, tôi sử dụng nó hai lần và lỗi chỉ hiện lên một lần.
Jelmer Mulder

45

Dựa trên câu trả lời của @Franck Dernoncourt, sửa -1 / 0:

def div0( a, b ):
    """ ignore / 0, div0( [-1, 0, 1], 0 ) -> [0, 0, 0] """
    with np.errstate(divide='ignore', invalid='ignore'):
        c = np.true_divide( a, b )
        c[ ~ np.isfinite( c )] = 0  # -inf inf NaN
    return c

div0( [-1, 0, 1], 0 )
array([0, 0, 0])

Cảm ơn, tôi thậm chí còn không bắt được lỗi đó với mã của @Frank Dernoncourt.
hlin117 29/02/16

Xin chào, tôi đang cố gắng làm toán mảng và tôi muốn 0/0 cho kết quả là 0 nhưng tôi cũng muốn bỏ qua np.NaN trong các phép tính của mình. Điều này sẽ làm việc cho điều đó? Ngoài ra, tôi đang cố gắng hiểu. C [~ np.isfinite (c)] = 0 làm gì? Tôi chưa bao giờ sử dụng ~ trong python. Nó dùng để làm gì? Cảm ơn bạn
user20408

@ user20408, ~đảo ngược TrueFalsetrong mảng NumPy: print ~ np.array([ True, False, False ]). c[ ~ np.isfinite( c )] = 0nghĩa là: tìm các vị trí mà ở đó clà hữu hạn, đảo các vị trí đó thành KHÔNG hữu hạn với ~và đặt các giá trị không hữu hạn thành 0. Xem thêm stackoverflow.com/search?q=[numpy]+"boolean+indexing "
denis

42

Xây dựng dựa trên các câu trả lời khác và cải thiện:

Mã:

import numpy as np

a = np.array([0,0,1,1,2], dtype='float')
b = np.array([0,1,0,1,3], dtype='float')

with np.errstate(divide='ignore', invalid='ignore'):
    c = np.true_divide(a,b)
    c[c == np.inf] = 0
    c = np.nan_to_num(c)

print('c: {0}'.format(c))

Đầu ra:

c: [ 0.          0.          0.          1.          0.66666667]

2
Làm tốt công việc kiểm tra 0/0cũng như 1/0sai sót.
hlin117

Tôi đã thử phương pháp của bạn với ví dụ mảng được đưa ra trong câu trả lời của DStauffman và có vẻ như để dẫn đến con số rất cao thay vì np.inf, mà vẫn ở kết quả cuối cùng
Gal Avineri

Tôi sẽ không khuyến khích cách tiếp cận này. Nếu một trong hai ahoặc bchứa NaN, thì 0kết quả là giải pháp của bạn đột ngột cho ra . Điều này có thể dễ dàng ẩn các lỗi trong mã của bạn và hoàn toàn không mong đợi.
DerWeh

Theo sách hướng dẫn numpy gần đây, nan_to_num () nhận các giá trị để thay thế cho inf dương và inf âm. numpy.nan_to_num(x, copy=True, nan=0.0, posinf=None, neginf=None)là chữ ký.
Craig Hicks

18

Một lớp lót (cảnh báo ném)

np.nan_to_num(array1 / array2)

13

Hãy thử làm điều đó trong hai bước. Phân chia trước, sau đó thay thế.

with numpy.errstate(divide='ignore'):
    result = numerator / denominator
    result[denominator == 0] = 0

Các numpy.errstatedòng là không bắt buộc, và chỉ ngăn chặn NumPy từ nói cho bạn về những "lỗi" chia cho số không, vì bạn đã có ý định làm như vậy, và xử lý các trường hợp đó.


5
Có lẽ bạn nên thực hiện các bộ phận trong bối cảnhnp.errstate(divide='ignore'):
Warren Weckesser

@WarrenWeckesser Điểm công bằng. Tôi đã chỉnh sửa câu trả lời để bao gồm ngữ cảnh. divide='warn'cũng có thể hữu ích nếu anh ấy / anh ấy muốn vẫn được thông báo.
Pi Marillion

2

Bạn cũng có thể thay thế dựa trên inf, chỉ khi các kiểu mảng là số nổi, theo câu trả lời sau:

>>> a = np.array([1,2,3], dtype='float')
>>> b = np.array([0,1,3], dtype='float')
>>> c = a / b
>>> c
array([ inf,   2.,   1.])
>>> c[c == np.inf] = 0
>>> c
array([ 0.,  2.,  1.])

0

Một câu trả lời mà tôi tìm thấy khi tìm kiếm một câu hỏi liên quan là thao tác đầu ra dựa trên việc mẫu số có bằng 0 hay không.

Giả sử arrayAarrayBđã được khởi tạo, nhưng arrayBcó một số số không. Chúng tôi có thể làm như sau nếu chúng tôi muốn tính toán arrayC = arrayA / arrayBmột cách an toàn.

Trong trường hợp này, bất cứ khi nào tôi có số chia cho 0 ở một trong các ô, tôi đặt ô đó bằng myOwnValue, trong trường hợp này sẽ là 0

myOwnValue = 0
arrayC = np.zeros(arrayA.shape())
indNonZeros = np.where(arrayB != 0)
indZeros = np.where(arrayB = 0)

# division in two steps: first with nonzero cells, and then zero cells
arrayC[indNonZeros] = arrayA[indNonZeros] / arrayB[indNonZeros]
arrayC[indZeros] = myOwnValue # Look at footnote

Chú thích cuối trang: Nhìn lại, dòng này dù sao cũng không cần thiết, vì arrayC[i]nó được khởi tạo bằng 0. Nhưng nếu là trường hợp đó myOwnValue != 0, hoạt động này sẽ làm được điều gì đó.


0

Một giải pháp khác đáng đề cập:

>>> a = np.array([1,2,3], dtype='float')
>>> b = np.array([0,1,3], dtype='float')
>>> b_inv = np.array([1/i if i!=0 else 0 for i in b])
>>> a*b_inv
array([0., 2., 1.])
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.