That's hard to answer because np.isnan and np.isfinite can use different C functions depending on the build. And depending on the performance (which may well depend on the compiler, the system and how NumPy itself is built) of these C functions the timings will be different.
The ufuncs for both refer to a built-in npy_ func (source (1.11.3)):
/**begin repeat1
* #kind = isnan, isinf, isfinite, signbit, copysign, nextafter, spacing#
* #func = npy_isnan, npy_isinf, npy_isfinite, npy_signbit, npy_copysign, nextafter, spacing#
**/
And these functions are defined based on the presence of compile time constants (source (1.11.3)):
/* use builtins to avoid function calls in tight loops
* only available if npy_config.h is available (= numpys own build) */
#if HAVE___BUILTIN_ISNAN
#define npy_isnan(x) __builtin_isnan(x)
#else
#ifndef NPY_HAVE_DECL_ISNAN
#define npy_isnan(x) ((x) != (x))
#else
#if defined(_MSC_VER) && (_MSC_VER < 1900)
#define npy_isnan(x) _isnan((x))
#else
#define npy_isnan(x) isnan(x)
#endif
#endif
#endif
/* only available if npy_config.h is available (= numpys own build) */
#if HAVE___BUILTIN_ISFINITE
#define npy_isfinite(x) __builtin_isfinite(x)
#else
#ifndef NPY_HAVE_DECL_ISFINITE
#ifdef _MSC_VER
#define npy_isfinite(x) _finite((x))
#else
#define npy_isfinite(x) !npy_isnan((x) + (-x))
#endif
#else
#define npy_isfinite(x) isfinite((x))
#endif
#endif
So it might just be that in your case the np.isfinite has to do (much) more work than np.isnan. But it's equally likely that on another computer or with another build np.isfinite is faster or both are equally fast.
So, there is probably not a hard rule what the "fastest way" is. That just depends on too many factors. Personally I would just go with the np.isfinite because it can be faster (and isn't too much slower even in your case) and it makes the intention much clearer.
Just in case you're really into optimizing the performance, you can always do the negating in-place. That might decrease the time and memory by avoiding one temporary array:
import numpy as np
arr = np.random.rand(1000000)
def isnotfinite(arr):
res = np.isfinite(arr)
np.bitwise_not(res, out=res) # in-place
return res
np.testing.assert_array_equal(~np.isfinite(arr), isnotfinite(arr))
np.testing.assert_array_equal(~np.isfinite(arr), np.isnan(arr - arr))
%timeit ~np.isfinite(arr)
# 3.73 ms ± 4.16 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit isnotfinite(arr)
# 2.41 ms ± 29.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit np.isnan(arr - arr)
# 12.5 ms ± 772 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Note also that the np.isnan solution is much slower on my computer (Windows 10 64bit Python 3.5 NumPy 1.13.1 Anaconda build)
That's hard to answer because np.isnan and np.isfinite can use different C functions depending on the build. And depending on the performance (which may well depend on the compiler, the system and how NumPy itself is built) of these C functions the timings will be different.
The ufuncs for both refer to a built-in npy_ func (source (1.11.3)):
/**begin repeat1
* #kind = isnan, isinf, isfinite, signbit, copysign, nextafter, spacing#
* #func = npy_isnan, npy_isinf, npy_isfinite, npy_signbit, npy_copysign, nextafter, spacing#
**/
And these functions are defined based on the presence of compile time constants (source (1.11.3)):
/* use builtins to avoid function calls in tight loops
* only available if npy_config.h is available (= numpys own build) */
#if HAVE___BUILTIN_ISNAN
#define npy_isnan(x) __builtin_isnan(x)
#else
#ifndef NPY_HAVE_DECL_ISNAN
#define npy_isnan(x) ((x) != (x))
#else
#if defined(_MSC_VER) && (_MSC_VER < 1900)
#define npy_isnan(x) _isnan((x))
#else
#define npy_isnan(x) isnan(x)
#endif
#endif
#endif
/* only available if npy_config.h is available (= numpys own build) */
#if HAVE___BUILTIN_ISFINITE
#define npy_isfinite(x) __builtin_isfinite(x)
#else
#ifndef NPY_HAVE_DECL_ISFINITE
#ifdef _MSC_VER
#define npy_isfinite(x) _finite((x))
#else
#define npy_isfinite(x) !npy_isnan((x) + (-x))
#endif
#else
#define npy_isfinite(x) isfinite((x))
#endif
#endif
So it might just be that in your case the np.isfinite has to do (much) more work than np.isnan. But it's equally likely that on another computer or with another build np.isfinite is faster or both are equally fast.
So, there is probably not a hard rule what the "fastest way" is. That just depends on too many factors. Personally I would just go with the np.isfinite because it can be faster (and isn't too much slower even in your case) and it makes the intention much clearer.
Just in case you're really into optimizing the performance, you can always do the negating in-place. That might decrease the time and memory by avoiding one temporary array:
import numpy as np
arr = np.random.rand(1000000)
def isnotfinite(arr):
res = np.isfinite(arr)
np.bitwise_not(res, out=res) # in-place
return res
np.testing.assert_array_equal(~np.isfinite(arr), isnotfinite(arr))
np.testing.assert_array_equal(~np.isfinite(arr), np.isnan(arr - arr))
%timeit ~np.isfinite(arr)
# 3.73 ms ± 4.16 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit isnotfinite(arr)
# 2.41 ms ± 29.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit np.isnan(arr - arr)
# 12.5 ms ± 772 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Note also that the np.isnan solution is much slower on my computer (Windows 10 64bit Python 3.5 NumPy 1.13.1 Anaconda build)
Using numba accelerator in parallel no-python mode will be faster than the isnotfinite function and ~np.isfinite @MSeifert answer, which are among the fastest methods. If we prepare an example data using:
def data_(m, n, f):
arr = np.random.random_integers(0, 10, m).astype(np.float64)
n_ = np.random.permutation(m)
arr[n_[:n//2]] = np.inf
arr[n_[n // 2:n]] = -np.inf
arr[n_[n:n+f]] = np.nan
return arr
So, ~np.isfinite can be jitted using numba as:
import numpy as np
import numba as nb
@nb.njit(parallel=True)
def numba_(arr):
res = np.empty(arr.shape[0], dtype=nb.boolean)
for i in nb.prange(arr.shape[0]):
res[i] = ~np.isfinite(arr[i])
return res
@nb.njit(parallel=True)
def numba_full(arr):
res = np.full(arr.shape[0], True)
for i in nb.prange(arr.shape[0]):
res[i] = ~np.isfinite(arr[i])
return res
Benchmark on Google Collaboratory CPU (horizontal axis is referring to m for data_):
temporary link to colab
