Cara mengembalikan 0 dengan membagi dengan nol

100

Saya mencoba melakukan pembagian bijak dengan python, tetapi jika angka nol ditemukan, saya perlu hasil bagi menjadi nol.

Sebagai contoh:

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

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

Saya selalu bisa menggunakan for-loop melalui data saya, tetapi untuk benar-benar memanfaatkan pengoptimalan numpy, saya memerlukan fungsi pembagian untuk mengembalikan 0 setelah membagi dengan nol kesalahan daripada mengabaikan kesalahan.

Kecuali saya melewatkan sesuatu, sepertinya numpy.seterr () dapat mengembalikan nilai saat terjadi kesalahan. Apakah ada yang punya saran lain tentang bagaimana saya bisa mendapatkan yang terbaik dari numpy sementara mengatur pembagian saya sendiri dengan penanganan kesalahan nol?

hlin117
sumber
Dalam versi python saya (Python 2.7.11 | Continuum Analytics, Inc.) itulah keluaran yang Anda dapatkan. Dengan peringatan.
Ramon Martinez
Jawaban benar yang paling ringkas adalah stackoverflow.com/a/37977222/2116338
mrplants

Jawaban:

182

Di numpy v1.7 +, Anda dapat memanfaatkan opsi "di mana" untuk ufuncs . Anda dapat melakukan banyak hal dalam satu baris dan Anda tidak perlu berurusan dengan pengelola konteks yang salah.

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

Dalam hal ini, ia melakukan kalkulasi bagi di mana saja 'di mana' b tidak sama dengan nol. Ketika b sama dengan nol, maka itu tetap tidak berubah dari nilai apa pun yang Anda berikan pada awalnya dalam argumen 'keluar'.

DStauffman
sumber
3
Jika adan / atau bmungkin array integer, maka itu konsep yang sama, Anda hanya perlu secara eksplisit mengatur jenis keluaran yang benar:c = np.divide(a, b, out=np.zeros(a.shape, dtype=float), where=b!=0)
DStauffman
out=np.zeros_like(a)sangat penting, seperti yang dinyatakan di baris komentar.
Jonatan Öström
1
Jika saya menggunakan np.divide(a, b, out=np.zeros_like(a), where=b!=0), saya mendapatkan kesalahan Assigning to function call which doesn't return. Yang aneh adalah, saya menggunakannya dua kali dan kesalahan hanya muncul sekali.
Jelmer Mulder
46

Berdasarkan jawaban @Franck Dernoncourt, memperbaiki -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])
denis
sumber
Terima kasih, saya bahkan tidak menemukan bug itu dengan kode @Frank Dernoncourt.
hlin117
Hai, saya mencoba melakukan matematika array dan saya ingin 0/0 menghasilkan 0 tetapi saya juga ingin mengabaikan np.NaN dalam perhitungan saya juga. Akankah ini berhasil untuk itu? Juga, saya mencoba untuk mengerti. Apa yang dilakukan c [~ np.isfinite (c)] = 0? Saya tidak pernah menggunakan ~ dengan python. Untuk apa ini? Terima kasih
pengguna20408
@ user20408, ~membalikkan Truedan Falsedalam array numpy: print ~ np.array([ True, False, False ]). c[ ~ np.isfinite( c )] = 0artinya: temukan posisi di mana cadalah finite, balikkan ke NOT finite with ~, dan setel nilai not finite ke 0. Lihat juga stackoverflow.com/search?q=[numpy]+"boolean+indexing "
denis
43

Membangun dari jawaban lain, dan meningkatkan:

Kode:

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

Keluaran:

c: [ 0.          0.          0.          1.          0.66666667]
Franck Dernoncourt
sumber
2
Pekerjaan yang baik untuk memeriksa 0/0serta 1/0kesalahan.
hlin117
Saya mencoba metode Anda dengan contoh array yang diberikan dalam jawaban DStauffman dan tampaknya menghasilkan angka yang sangat tinggi, bukan np.inf, yang tetap berada di hasil akhir
Gal Avineri
Saya akan mencegah pendekatan ini. Jika salah satu aatau bmengandung NaN, solusi Anda tiba-tiba memberi 0hasil. Ini dapat dengan mudah menyembunyikan kesalahan dalam kode Anda dan benar-benar tidak terduga.
DerWeh
Menurut manual numpy nan_to_num () mengambil nilai untuk menggantikan inf positif dan inf negatif juga. numpy.nan_to_num(x, copy=True, nan=0.0, posinf=None, neginf=None)adalah tanda tangannya.
Craig Hicks
18

One-liner (melempar peringatan)

np.nan_to_num(array1 / array2)
Ulf Aslak
sumber
13

Coba lakukan dalam dua langkah. Divisi dulu, lalu ganti.

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

The numpy.errstateline opsional, dan hanya mencegah NumPy dari memberitahu Anda tentang "kesalahan" membagi dengan nol, karena Anda sudah berniat untuk melakukannya, dan penanganan kasus itu.

Pi Marillion
sumber
5
Anda mungkin harus melakukan pembagian dalam konteksnp.errstate(divide='ignore'):
Warren Weckesser
@Warrener Poin yang adil. Saya telah mengedit jawabannya untuk memasukkan konteksnya. divide='warn'juga dapat berguna jika dia ingin tetap diberi tahu.
Pi Marillion
2

Anda juga dapat mengganti berdasarkan inf, hanya jika array dtypes adalah float, sesuai jawaban ini :

>>> 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.])
atomh33ls
sumber
0

Satu jawaban yang saya temukan saat mencari pertanyaan terkait adalah memanipulasi keluaran berdasarkan apakah penyebutnya nol atau tidak.

Misalkan arrayAdan arrayBtelah diinisialisasi, tetapi arrayBmemiliki beberapa angka nol. Kami dapat melakukan hal berikut jika ingin menghitung arrayC = arrayA / arrayBdengan aman.

Dalam hal ini, setiap kali saya membagi dengan nol di salah satu sel, saya mengatur sel menjadi sama dengan myOwnValue, yang dalam hal ini akan menjadi nol

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

Catatan kaki: Dalam retrospeksi, baris ini tidak diperlukan lagi, karena arrayC[i]dipakai ke nol. Tetapi jika kasusnya seperti itu myOwnValue != 0, operasi ini akan melakukan sesuatu.

hlin117
sumber
0

Solusi lain yang layak disebutkan:

>>> 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.])
T. Gwen
sumber