ゼロ除算で0を返す方法


100

私はpythonで要素ごとの除算を実行しようとしていますが、ゼロが検出された場合は、商をゼロにする必要があります。

例えば:

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

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

データを常にforループで使用することもできますが、numpyの最適化を実際に使用するには、エラーを無視するのではなく、ゼロエラーで除算するとゼロを返す除算関数が必要です。

私が何かを見逃していない限り、numpy.seterr()はエラー時に値を返すことができないようです。エラー処理で自分の除算を設定しているときに、私がいかにnumpyを最大限に活用できるかについて他の提案がありますか?


私のpythonバージョン(Python 2.7.11 | Continuum Analytics、Inc.)では、これがまさに得られる出力です。警告あり。
Ramon Martinez

最も簡潔な正解は、stackoverflow.com
a / 37977222/2116338

回答:


181

numpy v1.7 +では、ufuncsの「where」オプションを利用できます。物事を1行で行うことができ、errstateコンテキストマネージャを処理する必要はありません。

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

この場合、bがゼロに等しくない場所で除算計算を行います。bがゼロに等しい場合、「out」引数で最初に指定した値から変更されません。


2
場合aおよび/またはb:アレイの整数であるかもしれない、それは同じ概念だ、あなただけ明示的に正しい出力タイプを設定する必要がありますc = np.divide(a, b, out=np.zeros(a.shape, dtype=float), where=b!=0)
DStauffman

out=np.zeros_like(a)コメント行に記載されているように、重要です。
JonatanÖström

1
使用するnp.divide(a, b, out=np.zeros_like(a), where=b!=0)と、エラーが発生しますAssigning to function call which doesn't return。奇妙なことに、私はそれを2回使用し、エラーは1回しかポップアップしません。
Jelmer Mulder

45

@Franck Dernoncourtの回答に基づいて-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])

おかげで、@ Frank Dernoncourtのコードでそのバグを捕らえることさえできませんでした。
hlin117 2016

こんにちは、配列計算を実行しようとしています。0/ 0を0にしたいのですが、計算でもnp.NaNを無視したいと思います。これはそのために機能しますか?また、私は理解しようとしています。c [〜np.isfinite(c)] = 0は何をしますか?Pythonでは〜を使用したことがありません。それは何のため?ありがとう
user20408 2016年

@ user20408、~反転TrueFalsenumpyの配列で: print ~ np.array([ True, False, False ])c[ ~ np.isfinite( c )] = 0つまりc、有限の位置を見つけ、それらをNOTで有限に反転し~、非有限の値を0に設定します
。stackoverflow.com/ search

42

他の答えに基づいて構築し、改善する:

コード:

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

出力:

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

2
エラーのチェック0/0だけでなく、チェックにも1/0最適です。
hlin117 2015

DStauffmanの回答で示された例の配列を使用してメソッドを試したところ、np.infの代わりに非常に高い数値になり、最終結果に残っています
Gal Avineri

このアプローチはお勧めしません。いずれかの場合aまたはb含まれているNaN、あなたのソリューションが突然与え0、結果として。これはコードのエラーを簡単に隠すことができ、予期せぬ事態です。
ダーウェー

最近のnumpyマニュアルによると、 nan_to_num()は正のinfと負のinfの代わりに値を使用します。 numpy.nan_to_num(x, copy=True, nan=0.0, posinf=None, neginf=None)署名です。
クレイグヒックス


13

2つのステップで実行してみてください。最初に除算し、次に交換します。

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

このnumpy.errstate行はオプションであり、numpyがゼロで除算する「エラー」を通知しないようにしています。これは、すでにそうしているつもりであり、そのケースを処理しているためです。


5
あなたはおそらくコンテキストで除算を実行する必要がありますnp.errstate(divide='ignore'):
Warren Weckesser '

@WarrenWeckesserフェアポイント。コンテキストを含めるように回答を編集しました。divide='warn'通知を受けたい場合にも役立ちます。
Pi Marillion 2014年

2

この回答のinfように、配列のdtypeがfloatの場合にのみ、に基づいて置き換えることもできます

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

私が関連する質問を検索して見つけた1つの答えは、分母がゼロかどうかに基づいて出力を操作することでした。

初期化されているが、ゼロがいくつかあるarrayAとしarrayBますarrayBarrayC = arrayA / arrayB安全に計算したい場合は、次のようにすることができます。

この場合、セルの1つでゼロによる除算がある場合は常に、セルをに設定します。myOwnValueこの場合、セルはゼロになります。

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

脚注:振り返ってみると、この行はarrayC[i]ゼロにインスタンス化されているため、とにかく不要です。しかし、もしそうならmyOwnValue != 0、この操作は何かをします。


0

言及する価値のある他の解決策:

>>> 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.])
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.