Sıfıra bölme ile 0 nasıl döndürülür


106

Python'da element bilge bölme yapmaya çalışıyorum, ancak sıfırla karşılaşılırsa, bölümün sadece sıfır olmasına ihtiyacım var.

Örneğin:

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

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

Verilerimde her zaman bir for-loop kullanabilirdim, ancak numpy'nin optimizasyonlarından gerçekten yararlanmak için, hatayı göz ardı etmek yerine sıfır hataya böldüğünde 0 döndürmek için bölme işlevine ihtiyacım var.

Bir şeyi kaçırmadığım sürece, numpy.seterr () hata durumunda değer döndürebilir. Sıfır hata işlemeyle kendi bölmemi ayarlarken uyuşukluktan en iyi şekilde nasıl yararlanabileceğim konusunda başka önerileri olan var mı?


Python sürümümde (Python 2.7.11 | Continuum Analytics, Inc.) tam olarak aldığınız çıktı budur. Bir uyarı ile.
Ramon Martinez

En kısa ve öz doğru cevap stackoverflow.com/a/37977222/2116338
mrplants

Yanıtlar:


197

Numpy v1.7 + 'da ufunc'lar için "where" seçeneğinden yararlanabilirsiniz . İşleri tek satırda yapabilirsiniz ve hatalı durum bağlam yöneticisiyle uğraşmanıza gerek kalmaz.

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

Bu durumda, bölme hesaplamasını b'nin sıfıra eşit olmadığı herhangi bir yerde yapar. B sıfıra eşit olduğunda, ona başlangıçta "çıkış" argümanında verdiğiniz değerden değişmeden kalır.


4
Eğer ave / veya bdizide tamsayı olabilir, o zaman aynı konsept, sadece açıkça belirlenen doğru çıktı tipine ihtiyaç var:c = np.divide(a, b, out=np.zeros(a.shape, dtype=float), where=b!=0)
DStauffman

out=np.zeros_like(a)yorum satırında belirtildiği gibi kritiktir.
Jonatan Öström

1
Ben kullanırsanız np.divide(a, b, out=np.zeros_like(a), where=b!=0), ben hata alıyorum Assigning to function call which doesn't return. Garip olan şey, onu iki kez kullanıyorum ve hata sadece bir kez çıkıyor.
Jelmer Mulder

1
Hangisinin en hızlı olduğu ile ilgilenen olursa, bu yöntem @ denis'in / @ Franck Dernoncourt'un cevabından daha hızlıdır, bir milyon döngü çalıştırarak bunun için 8 saniye, onlarınki için 11 saniye alıyorum.
kory

49

@Franck Dernoncourt'un cevabına dayanarak -1 / 0'ı düzelterek:

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

Teşekkürler, @Frank Dernoncourt'un koduyla o hatayı yakalayamadım bile.
hlin117

Merhaba, dizi matematiği yapmaya çalışıyorum ve 0 / 0'ın 0 ile sonuçlanmasını istiyorum ama aynı zamanda hesaplamalarımda np.NaN'yi de göz ardı etmek istiyorum. Bu bunun için işe yarayacak mı? Ayrıca anlamaya çalışıyorum. C [~ np.isfinite (c)] = 0 ne yapar? Python'da hiç ~ kullanmadım. Bu ne için? Teşekkür ederim
user20408

@ user20408, ~tersine döndüğü Trueve Falsenumpy dizide: print ~ np.array([ True, False, False ]). c[ ~ np.isfinite( c )] = 0şu anlama gelir: csonlu olan konumları bulun, bunları sonlu OLMAYAN olarak ters çevirin ~ve sonlu olmayan değerleri 0'a ayarlayın. Ayrıca bkz. stackoverflow.com/search?q=[numpy]+"boolean+indexing "
denis

45

Diğer yanıtlar üzerine inşa etmek ve şu konularda geliştirmek:

Kod:

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

Çıktı:

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

2
Hataların 0/0yanı sıra kontrol etmek için iyi bir iş 1/0.
hlin117

Yönteminizi DStauffman'ın cevabında verilen örnek dizilerle denedim ve sonuçta np.inf yerine çok yüksek sayılarla sonuçlanıyor gibi görünüyor
Gal Avineri

Bu yaklaşımı caydırırdım. Bunlardan biri aveya biçeriyorsa NaN, çözümünüz aniden 0sonuç olarak verir . Bu, kodunuzdaki hataları kolayca gizleyebilir ve kesinlikle beklenmedik bir durumdur.
DerWeh

Yakın zamandaki numpy kılavuzuna göre nan_to_num (), pozitif inf ve negatif inf yerine koymak için değerler alıyor. numpy.nan_to_num(x, copy=True, nan=0.0, posinf=None, neginf=None)imzadır.
Craig Hicks

19

Tek satırlık (uyarı atar)

np.nan_to_num(array1 / array2)

14

Bunu iki adımda yapmayı deneyin. Önce bölün, sonra değiştirin.

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

numpy.errstateÇizgi isteğe bağlıdır ve zaten bunu yapmak isteyen ve bu talebi işleme ediyoruz çünkü sadece önler, sıfıra bölme işlemi "hata" Size sözünü gelen numpy.


5
np.errstate(divide='ignore'):
Bölmeyi

@WarrenWeckesser Fuar noktası. Cevabı bağlamı içerecek şekilde düzenledim. divide='warn'yine de bilgilendirilmek istiyorsa yararlı olabilir.
Pi Marillion

2

Ayrıca dayalı replace edebilirsiniz infdizi dtypes göre, yüzer sadece eğer bu cevap :

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

İlgili bir soruyu ararken bulduğum yanıtlardan biri, paydanın sıfır olup olmadığına bağlı olarak çıktıyı değiştirmek oldu.

Varsayalım arrayAve arrayBbaşlatıldı, ancak arrayBbazı sıfırlar var. arrayC = arrayA / arrayBGüvenli bir şekilde hesaplamak istiyorsak aşağıdakileri yapabiliriz .

Bu durumda, hücrelerden birinde sıfıra bölünme olduğunda, hücreyi eşit olacak şekilde ayarlıyorum, myOwnValuebu durumda bu sıfır olacaktır

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

Dipnot: Geriye dönüp bakıldığında, arrayC[i]sıfıra örneklendiği için bu satır zaten gereksizdir . Ama böyle olsaydı myOwnValue != 0, bu operasyon bir şeyler yapacaktı.


0

Bahsetmeye değer başka bir çözüm:

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