0으로 나누고 0을 반환하는 방법


100

파이썬에서 요소 현명한 나누기를 수행하려고하지만 0이 발생하면 몫이 0이되어야합니다.

예를 들면 :

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

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

항상 내 데이터를 통해 for 루프를 사용할 수 있지만 실제로 numpy의 최적화를 활용하려면 오류를 무시하는 대신 0으로 나누기 오류를 0으로 반환하는 나누기 함수가 필요합니다.

내가 뭔가를 놓치고 있지 않는 한 numpy.seterr () 이 오류에 대해 값을 반환 할 수있는 것 같지 않습니다 . 누구든지 0으로 나누기 오류 처리를 설정하는 동안 numpy에서 최선을 다할 수있는 방법에 대한 다른 제안이 있습니까?


내 파이썬 버전 (Python 2.7.11 | Continuum Analytics, Inc.)에서 그것은 정확히 당신이 얻는 출력입니다. 경고와 함께.
Ramon Martinez

가장 간결한 정답은 stackoverflow.com/a/37977222/2116338
mrplants

답변:


181

numpy v1.7 이상에서는 ufuncs 에 대한 "where"옵션을 활용할 수 있습니다. 한 줄로 작업을 수행 할 수 있으며 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]

이 경우 'where'b가 0이 아닌 곳에서 나누기 계산을 수행합니다. b가 0과 같으면 원래 'out'인수에서 제공 한 값에서 변경되지 않습니다.


3
경우 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합니다. 이상한 점은 두 번 사용하고 오류가 한 번만 나타납니다.
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

안녕하세요, 배열 수학을하려고하는데 0/0이 0이 되길 원하지만 계산에서도 np.NaN을 무시하고 싶습니다. 이것이 효과가 있습니까? 또한 이해하려고 노력하고 있습니다. c [~ np.isfinite (c)] = 0은 무엇을합니까? 나는 파이썬에서 ~를 사용한 적이 없습니다. 그것은 무엇입니까? 감사합니다
user20408

@ user20408, ~반전 TrueFalsenumpy 배열 : print ~ np.array([ True, False, False ]). c[ ~ np.isfinite( c )] = 0의미 : c유한 한 위치를 찾고,를 사용하여 유한하지 않음으로 반전하고 ~, 비 한정 값을 0으로 설정합니다. 참조 : stackoverflow.com/search?q=[numpy]+"boolean+indexing "
denis

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

DStauffman의 답변에 제공된 예제 배열로 방법을 시도했는데 최종 결과에 남아있는 np.inf 대신 매우 높은 숫자가 나타나는 것 같습니다
Gal Avineri

이 접근 방식을 권장하지 않습니다. a또는 b포함하는 경우 NaN솔루션이 갑자기 0결과를 제공합니다 . 이것은 코드의 오류를 쉽게 숨길 수 있으며 전혀 예상치 못한 일입니다.
DerWeh

최근 numpy 매뉴얼 에 따르면 nan_to_num ()은 양의 inf와 음의 inf를 대체하기 위해 값을 취합니다. numpy.nan_to_num(x, copy=True, nan=0.0, posinf=None, neginf=None)서명입니다.
Craig Hicks


13

두 단계로 시도하십시오. 먼저 분할 한 다음 교체하십시오.

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

numpy.errstate줄은 선택 사항이며 numpy가 0으로 나누는 "오류"에 대해 알려주지 않습니다. 이미 그렇게하려고했기 때문에 그 경우를 처리합니다.


5
당신은 아마 맥락에서 분할을 수행해야합니다np.errstate(divide='ignore'):
워렌 Weckesser에게

@WarrenWeckesser 공정한 지점. 컨텍스트를 포함하도록 답변을 편집했습니다. divide='warn'알림을 받고 싶은 경우에도 유용 할 수 있습니다.
Pi Marillion

2

이 답변에inf 따라 배열 dtypes가 부동 소수점 인 경우에만을 기준으로 바꿀 수도 있습니다 .

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

관련 질문을 검색하면서 찾은 한 가지 대답은 분모가 0인지 아닌지에 따라 출력을 조작하는 것입니다.

가정 arrayAarrayB초기화되었지만, arrayB일부 0을 가지고있다. arrayC = arrayA / arrayB안전하게 계산하려면 다음을 수행 할 수 있습니다.

이 경우 셀 중 하나에서 0으로 나누기를 할 때마다 셀을으로 설정합니다 myOwnValue.이 경우에는 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

각주 : 돌이켜 보면이 줄은 arrayC[i]0으로 인스턴스화 되었으므로 어쨌든 불필요 합니다. 그러나 만약 그렇다면 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.