sourcecode

NumPy 배열에 숫자가 아닌 값이 하나 이상 포함되어 있는지 탐지하시겠습니까?

codebag 2023. 7. 27. 21:57
반응형

NumPy 배열에 숫자가 아닌 값이 하나 이상 포함되어 있는지 탐지하시겠습니까?

입력에 숫자가 아닌 하나 이상의 값이 포함되어 있는지 감지하는 함수를 작성해야 합니다.숫자가 아닌 값이 발견되면 오류가 발생합니다(계산은 숫자 값만 반환해야 하므로).입력 배열의 치수 수는 미리 알 수 없습니다. 함수는 ndim과 관계없이 정확한 값을 제공해야 합니다.추가적인 복잡성으로 입력은 단일 플로트 또는numpy.float64아니면 심지어 0차원 배열 같은 이상한 것도.

이 문제를 해결하는 분명한 방법은 배열에서 반복 가능한 모든 개체에 대해 비-이터라베를 찾을 때까지 반복하는 재귀 함수를 작성하는 것입니다.다음을 적용합니다.numpy.isnan()모든 반복할 수 없는 개체에 대한 함수입니다.숫자가 아닌 값이 하나 이상 발견되면 함수는 즉시 False를 반환합니다.그렇지 않으면 반복 가능한 모든 값이 숫자인 경우 True가 반환됩니다.

그것은 잘 작동하지만, 꽤 느리고, 는 NumPy가 훨씬 더 나은 방법을 가지고 있다고 기대합니다.더 빠르고 더 무기력한 대안은 무엇입니까?

다음은 제 모형입니다.

def contains_nan( myarray ):
    """
    @param myarray : An n-dimensional array or a single float
    @type myarray : numpy.ndarray, numpy.array, float
    @returns: bool
    Returns true if myarray is numeric or only contains numeric values.
    Returns false if at least one non-numeric value exists
    Not-A-Number is given by the numpy.isnan() function.
    """
    return True

이 작업은 반복하는 것보다 빨라야 하며 모양에 관계없이 작동합니다.

numpy.isnan(myarray).any()

편집: 30배 더 빠름:

import timeit
s = 'import numpy;a = numpy.arange(10000.).reshape((100,100));a[10,10]=numpy.nan'
ms = [
    'numpy.isnan(a).any()',
    'any(numpy.isnan(x) for x in a.flatten())']
for m in ms:
    print "  %.2f s" % timeit.Timer(m, s).timeit(1000), m

결과:

  0.11 s numpy.isnan(a).any()
  3.75 s any(numpy.isnan(x) for x in a.flatten())

보너스: 어레이가 아닌 NumPy 유형에 적합합니다.

>>> a = numpy.float64(42.)
>>> numpy.isnan(a).any()
False
>>> a = numpy.float64(numpy.nan)
>>> numpy.isnan(a).any()
True

무한대가 가능한 값이라면 numpy.isfinite를 사용할 것입니다.

numpy.isfinite(myarray).all()

위 사항이 다음과 같이 평가되는 경우True,그리고나서myarray포함되지 않음numpy.nan,numpy.inf또는-numpy.inf.

numpy.isnan괜찮으실 겁니다numpy.inf값, 예:

In [11]: import numpy as np

In [12]: b = np.array([[4, np.inf],[np.nan, -np.inf]])

In [13]: np.isnan(b)
Out[13]: 
array([[False, False],
       [ True, False]], dtype=bool)

In [14]: np.isfinite(b)
Out[14]: 
array([[ True, False],
       [False, False]], dtype=bool)

잠깐만! 마이크로초!나노초 안에 해결할 수 있는 문제를 마이크로초 안에 절대 풀지 마세요.

허용된 답변:

  • 난이 발견되었는지 여부에 관계없이 전체 데이터에 대해 반복합니다.
  • 크기가 N인 임시 배열을 생성합니다. 이 배열은 중복됩니다.

더 나은 해결책은 NAN이 발견되면 True를 즉시 반환하는 것입니다.

import numba
import numpy as np

NAN = float("nan")

@numba.njit(nogil=True)
def _any_nans(a):
    for x in a:
        if np.isnan(x): return True
    return False

@numba.jit
def any_nans(a):
    if not a.dtype.kind=='f': return False
    return _any_nans(a.flat)

array1M = np.random.rand(1000000)
assert any_nans(array1M)==False
%timeit any_nans(array1M)  # 573us

array1M[0] = NAN
assert any_nans(array1M)==True
%timeit any_nans(array1M)  # 774ns  (!nanoseconds)

n차원에서 작동합니다.

array1M_nd = array1M.reshape((len(array1M)/2, 2))
assert any_nans(array1M_nd)==True
%timeit any_nans(array1M_nd)  # 774ns

이를 numpy 네이티브 솔루션과 비교해 보십시오.

def any_nans(a):
    if not a.dtype.kind=='f': return False
    return np.isnan(a).any()

array1M = np.random.rand(1000000)
assert any_nans(array1M)==False
%timeit any_nans(array1M)  # 456us

array1M[0] = NAN
assert any_nans(array1M)==True
%timeit any_nans(array1M)  # 470us

%timeit np.isnan(array1M).any()  # 532us

조기 종료 방법은 3개 주문 또는 매그니튜드 속도 향상(경우에 따라)입니다.간단한 주석을 달기에는 너무 초라하지 않습니다.

(np.where(np.isnan(A)))[0].shape[0]보다 클 것입니다.0한다면A의 요소를 하나 이상 포함합니다.nan,A그럴 수도 있습니다n x m매트릭스.

예:

import numpy as np

A = np.array([1,2,4,np.nan])

if (np.where(np.isnan(A)))[0].shape[0]: 
    print "A contains nan"
else:
    print "A does not contain nan"

numpy 1.3 또는 svn을 사용하여 이를 수행할 수 있습니다.

In [1]: a = arange(10000.).reshape(100,100)

In [3]: isnan(a.max())
Out[3]: False

In [4]: a[50,50] = nan

In [5]: isnan(a.max())
Out[5]: True

In [6]: timeit isnan(a.max())
10000 loops, best of 3: 66.3 µs per loop

비교에서 난스의 처리는 이전 버전에서 일관되지 않았습니다.

언급URL : https://stackoverflow.com/questions/911871/detect-if-a-numpy-array-contains-at-least-one-non-numeric-value

반응형