numpy数组的元素明智测试是数值

Wei*_* Li 6 python arrays numpy

我有一个数组如下:

In [1]: x = array(['1.2', '2.3', '1.2.3'])
Run Code Online (Sandbox Code Playgroud)

我想测试数组中的每个元素是否可以转换为数值。也就是说,函数:is_numeric(x)将返回True / False数组,如下所示:

In [2]: is_numeric(x)
Out[2]: array([True, True, False])
Run Code Online (Sandbox Code Playgroud)

这该怎么做?

dra*_*fly 6

import numpy as np

def is_float(val):
        try:
            float(val)
        except ValueError:
            return False
        else:
            return True

a = np.array(['1.2', '2.3', '1.2.3'])

is_numeric_1 = lambda x: map(is_float, x)              # return python list
is_numeric_2 = lambda x: np.array(map(is_float, x))    # return numpy array
is_numeric_3 = np.vectorize(is_float, otypes = [bool]) # return numpy array
Run Code Online (Sandbox Code Playgroud)

取决于大小一个阵列和返回值的类型,这些函数具有不同的速度。

In [26]: %timeit is_numeric_1(a)
100000 loops, best of 3: 2.34 µs per loop

In [27]: %timeit is_numeric_2(a)
100000 loops, best of 3: 3.13 µs per loop

In [28]: %timeit is_numeric_3(a)
100000 loops, best of 3: 6.7 µs per loop

In [29]: a = np.array(['1.2', '2.3', '1.2.3']*1000)

In [30]: %timeit is_numeric_1(a)
1000 loops, best of 3: 1.53 ms per loop

In [31]: %timeit is_numeric_2(a)
1000 loops, best of 3: 1.6 ms per loop

In [32]: %timeit is_numeric_3(a)
1000 loops, best of 3: 1.58 ms per loop
Run Code Online (Sandbox Code Playgroud)

如果list没问题,请使用is_numeric_1.

如果你想numpy array和规模小,使用is_numeric_2

否则,使用 is_numeric_3


Wei*_* Li 1

我发现以下内容很适合我的目的。

首先,将https://rosettacode.org/wiki/Determine_if_a_string_is_numeric#C中的 isNumeric 函数保存在名为 ctest.h 的文件中,然后创建一个 .pyx 文件,如下所示:

from numpy cimport ndarray, uint8_t
import numpy as np
cimport numpy as np

cdef extern from "ctest.h":
     int isNumeric(const char * s)

def is_numeric_elementwise(ndarray x):
    cdef Py_ssize_t i
    cdef ndarray[uint8_t, mode='c', cast=True] y = np.empty_like(x, dtype=np.uint8)

    for i in range(x.size):
        y[i] = isNumeric(x[i])

    return y > 0
Run Code Online (Sandbox Code Playgroud)

上面的 Cython 函数运行速度相当快。

In [4]: is_numeric_elementwise(array(['1.2', '2.3', '1.2.3']))
Out[4]: array([ True,  True, False], dtype=bool)

In [5]: %timeit is_numeric_elementwise(array(['1.2', '2.3', '1.2.3'] * 1000000))
1 loops, best of 3: 695 ms per loop
Run Code Online (Sandbox Code Playgroud)

/sf/answers/2659837141/中的 is_numeric_3 方法相比,速度快了约 5 倍。

In [6]: %timeit is_numeric_3(array(['1.2', '2.3', '1.2.3'] * 1000000))
1 loops, best of 3: 3.45 s per loop
Run Code Online (Sandbox Code Playgroud)

我想可能还有一些需要改进的地方。