np.nan
NumPy 배열에서 NaN ( ) 발생을 확인하는 가장 빠른 방법을 찾고 X
있습니다. np.isnan(X)
그것은 X.shape
잠재적으로 거대한 shape의 부울 배열을 구축하기 때문에 의문의 여지 가 없습니다.
시도 np.nan in X
했지만 작동하지 않는 것 같습니다 np.nan != np.nan
. 이 작업을 수행하는 빠르고 메모리 효율적인 방법이 있습니까?
( “얼마나 거대”냐고 묻는 사람들에게 : 모르겠다. 이것은 라이브러리 코드에 대한 입력 유효성 검사입니다.)
답변
Ray의 솔루션이 좋습니다. 그러나 내 컴퓨터 numpy.sum
에서는 다음 대신 사용하는 것이 약 2.5 배 빠릅니다 numpy.min
.
In [13]: %timeit np.isnan(np.min(x))
1000 loops, best of 3: 244 us per loop
In [14]: %timeit np.isnan(np.sum(x))
10000 loops, best of 3: 97.3 us per loop
와 달리 min
, sum
는 분기가 필요하지 않으며, 최신 하드웨어에서는 비용이 많이 드는 경향이 있습니다. 이것이 아마도 sum
더 빠른 이유 일 것입니다 .
edit 위의 테스트는 어레이 중간에 단일 NaN을 사용하여 수행되었습니다.
min
NaN이 없을 때보 다 NaN이있을 때 더 느리다는 점은 흥미 롭습니다 . NaN이 어레이의 시작에 가까워 질수록 속도가 느려지는 것 같습니다. 반면에 sum
의 처리량은 NaN이 있는지 여부와 위치에 관계없이 일정하게 보입니다.
In [40]: x = np.random.rand(100000)
In [41]: %timeit np.isnan(np.min(x))
10000 loops, best of 3: 153 us per loop
In [42]: %timeit np.isnan(np.sum(x))
10000 loops, best of 3: 95.9 us per loop
In [43]: x[50000] = np.nan
In [44]: %timeit np.isnan(np.min(x))
1000 loops, best of 3: 239 us per loop
In [45]: %timeit np.isnan(np.sum(x))
10000 loops, best of 3: 95.8 us per loop
In [46]: x[0] = np.nan
In [47]: %timeit np.isnan(np.min(x))
1000 loops, best of 3: 326 us per loop
In [48]: %timeit np.isnan(np.sum(x))
10000 loops, best of 3: 95.9 us per loop
답변
나는 np.isnan(np.min(X))
당신이 원하는 것을해야 한다고 생각 합니다.
답변
받아 들여지는 대답이 있더라도 다음을 보여주고 싶습니다 (Vista의 Python 2.7.2 및 Numpy 1.6.0 사용).
In []: x= rand(1e5)
In []: %timeit isnan(x.min())
10000 loops, best of 3: 200 us per loop
In []: %timeit isnan(x.sum())
10000 loops, best of 3: 169 us per loop
In []: %timeit isnan(dot(x, x))
10000 loops, best of 3: 134 us per loop
In []: x[5e4]= NaN
In []: %timeit isnan(x.min())
100 loops, best of 3: 4.47 ms per loop
In []: %timeit isnan(x.sum())
100 loops, best of 3: 6.44 ms per loop
In []: %timeit isnan(dot(x, x))
10000 loops, best of 3: 138 us per loop
따라서 실제로 효율적인 방법은 운영 체제에 크게 의존 할 수 있습니다. 어쨌든 dot(.)
기반이 가장 안정적인 것 같습니다.
답변
여기에는 두 가지 일반적인 접근 방식이 있습니다.
- 각 어레이 항목을 확인
nan
하고any
. nan
s (예 :)를 보존하는 누적 연산을 적용sum
하고 그 결과를 확인합니다.
첫 번째 접근 방식은 확실히 가장 깔끔하지만 일부 누적 작업 (특히,와 같이 BLAS에서 실행되는 작업)을 과도하게 최적화 dot
하면이를 매우 빠르게 만들 수 있습니다. 그주의 dot
다른 BLAS 작업과 같은 특정 조건에서 멀티 스레드있다. 이것은 다른 기계 간의 속도 차이를 설명합니다.
import numpy
import perfplot
def min(a):
return numpy.isnan(numpy.min(a))
def sum(a):
return numpy.isnan(numpy.sum(a))
def dot(a):
return numpy.isnan(numpy.dot(a, a))
def any(a):
return numpy.any(numpy.isnan(a))
def einsum(a):
return numpy.isnan(numpy.einsum("i->", a))
perfplot.show(
setup=lambda n: numpy.random.rand(n),
kernels=[min, sum, dot, any, einsum],
n_range=[2 ** k for k in range(20)],
logx=True,
logy=True,
xlabel="len(a)",
)
답변
-
.any () 사용
if numpy.isnan(myarray).any()
-
numpy.isfinite는 확인을 위해 isnan보다 낫습니다.
if not np.isfinite(prop).all()
답변
당신이 편안하다면 누바 빠른 단락 (NaN이 발견되는 즉시 중지) 기능을 생성 할 수 있습니다.
import numba as nb
import math
@nb.njit
def anynan(array):
array = array.ravel()
for i in range(array.size):
if math.isnan(array[i]):
return True
return False
NaN
함수가 실제로 더 느릴 수 없다면 큰 배열에 다중 처리를 사용 np.min
하기 때문이라고 생각 np.min
합니다.
import numpy as np
array = np.random.random(2000000)
%timeit anynan(array) # 100 loops, best of 3: 2.21 ms per loop
%timeit np.isnan(array.sum()) # 100 loops, best of 3: 4.45 ms per loop
%timeit np.isnan(array.min()) # 1000 loops, best of 3: 1.64 ms per loop
그러나 배열에 NaN이있는 경우, 특히 위치가 낮은 인덱스에 있으면 훨씬 빠릅니다.
array = np.random.random(2000000)
array[100] = np.nan
%timeit anynan(array) # 1000000 loops, best of 3: 1.93 µs per loop
%timeit np.isnan(array.sum()) # 100 loops, best of 3: 4.57 ms per loop
%timeit np.isnan(array.min()) # 1000 loops, best of 3: 1.65 ms per loop
Cython 또는 C 확장을 사용하여 유사한 결과를 얻을 수 있습니다. 이들은 조금 더 복잡하거나 (또는 쉽게 사용할 수 있음 bottleneck.anynan
) 내 anynan
기능 과 동일한 작업을 수행합니다 .
답변
이와 관련하여 NaN의 첫 번째 발생을 찾는 방법에 대한 질문이 있습니다. 이것이 내가 아는 것을 처리하는 가장 빠른 방법입니다.
index = next((i for (i,n) in enumerate(iterable) if n!=n), None)