NumPy 배열에 숫자가 아닌 값이 하나 이상 포함되어 있는지 감지 하시겠습니까?
입력에 숫자가 아닌 값이 하나 이상 포함되어 있는지 감지하는 함수를 작성해야합니다. 숫자가 아닌 값이 발견되면 오류가 발생합니다 (계산은 숫자 값만 반환해야하기 때문). 입력 배열의 차원 수는 미리 알 수 없습니다. 함수는 ndim에 관계없이 올바른 값을 제공해야합니다. 추가 복잡함으로 입력은 단일 플로트 또는 numpy.float64
0 차원 배열과 같은 이상한 무언가 일 수 있습니다 .
이 문제를 해결하는 확실한 방법은 비 iterabe를 찾을 때까지 배열의 모든 반복 가능한 객체를 반복하는 재귀 함수를 작성하는 것입니다. 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
no numpy.nan
, numpy.inf
또는 -numpy.inf
값이 포함 됩니다.
numpy.nan
함께 OK 것 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)
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
비교에서 nan의 처리는 이전 버전에서 일관되지 않았습니다.
(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"
Pfft! 마이크로 초! 나노초 단위로 해결할 수있는 문제를 마이크로 초 단위로 해결하지 마십시오.
허용되는 답변은 다음과 같습니다.
- nan이 발견되었는지 여부에 관계없이 전체 데이터를 반복합니다.
- 중복되는 크기 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
The early-exit method is 3 orders or magnitude speedup (in some cases). Not too shabby for a simple annotation.
'programing' 카테고리의 다른 글
Bash 배열에서 요소 제거 (0) | 2020.09.21 |
---|---|
OS X 터미널 바로 가기 : 줄의 시작 / 끝으로 이동 (0) | 2020.09.21 |
IFRAME에서 현재 URL 가져 오기 (0) | 2020.09.21 |
ASP.NET MVC 작업에서 리퍼러 URL을 얻으려면 어떻게합니까? (0) | 2020.09.21 |
Java에서 유효한 URL을 확인하는 방법은 무엇입니까? (0) | 2020.09.21 |