如果我有一个numpy dtype,我如何自动将其转换为最接近的python数据类型?例如,

numpy.float32 -> "python float"
numpy.float64 -> "python float"
numpy.uint32  -> "python int"
numpy.int16   -> "python int"

我可以尝试提出所有这些情况的映射,但是numpy是否提供了一些自动的方法来将其dtypes转换为尽可能接近的本机python类型?这种映射不需要是详尽的,但它应该转换具有类似python的常见dtype。我想这已经在numpy的某个地方发生了。


当前回答

如果你想转换(numpy。数组或numpy标量或本机类型或numpy.darray)本机类型你可以简单地做:

converted_value = getattr(value, "tolist", lambda: value)()

Tolist会将标量或数组转换为python原生类型。默认的lambda函数处理值已经是本机的情况。

其他回答

使用val.item()将大多数NumPy值转换为原生Python类型:

import numpy as np

# for example, numpy.float32 -> python float
val = np.float32(0)
pyval = val.item()
print(type(pyval))         # <class 'float'>

# and similar...
type(np.float64(0).item()) # <class 'float'>
type(np.uint32(0).item())  # <class 'int'>
type(np.int16(0).item())   # <class 'int'>
type(np.cfloat(0).item())  # <class 'complex'>
type(np.datetime64(0, 'D').item())  # <class 'datetime.date'>
type(np.datetime64('2001-01-01 00:00:00').item())  # <class 'datetime.datetime'>
type(np.timedelta64(0, 'D').item()) # <class 'datetime.timedelta'>
...

(另一个方法是np.asscalar(val),但自NumPy 1.16以来已弃用)。


对于好奇的人来说,为您的系统构建一个NumPy数组标量转换表:

for name in dir(np):
    obj = getattr(np, name)
    if hasattr(obj, 'dtype'):
        try:
            if 'time' in name:
                npn = obj(0, 'D')
            else:
                npn = obj(0)
            nat = npn.item()
            print('{0} ({1!r}) -> {2}'.format(name, npn.dtype.char, type(nat)))
        except:
            pass

在一些系统中,有一些NumPy类型在Python中没有对应的原生类型,包括:clongdouble, clongfloat, complex192, complex256, float128, longcomplex, longdouble和longfloat。在使用.item()之前,需要将它们转换为最接近的NumPy等效值。

我的方法有点强硬,但似乎适用于所有情况:

def type_np2py(dtype=None, arr=None):
    '''Return the closest python type for a given numpy dtype'''

    if ((dtype is None and arr is None) or
        (dtype is not None and arr is not None)):
        raise ValueError(
            "Provide either keyword argument `dtype` or `arr`: a numpy dtype or a numpy array.")

    if dtype is None:
        dtype = arr.dtype

    #1) Make a single-entry numpy array of the same dtype
    #2) force the array into a python 'object' dtype
    #3) the array entry should now be the closest python type
    single_entry = np.empty([1], dtype=dtype).astype(object)

    return type(single_entry[0])

用法:

>>> type_np2py(int)
<class 'int'>

>>> type_np2py(np.int)
<class 'int'>

>>> type_np2py(str)
<class 'str'>

>>> type_np2py(arr=np.array(['hello']))
<class 'str'>

>>> type_np2py(arr=np.array([1,2,3]))
<class 'int'>

>>> type_np2py(arr=np.array([1.,2.,3.]))
<class 'float'>

对不起,这部分来晚了,但我正在寻找一个转换numpy的问题。float64只适用于常规Python浮点数。我看到了3种方法:

npValue.item () npValue.astype(浮动) 浮动(npValue)

以下是IPython的相关计时:

In [1]: import numpy as np

In [2]: aa = np.random.uniform(0, 1, 1000000)

In [3]: %timeit map(float, aa)
10 loops, best of 3: 117 ms per loop

In [4]: %timeit map(lambda x: x.astype(float), aa)
1 loop, best of 3: 780 ms per loop

In [5]: %timeit map(lambda x: x.item(), aa)
1 loop, best of 3: 475 ms per loop

听起来float(npValue)似乎更快。

对于那些不需要自动转换并且知道值的numpy dtype的人来说,关于数组标量的一个旁注:

Array scalars differ from Python scalars, but for the most part they can be used interchangeably (the primary exception is for versions of Python older than v2.x, where integer array scalars cannot act as indices for lists and tuples). There are some exceptions, such as when code requires very specific attributes of a scalar or when it checks specifically whether a value is a Python scalar. Generally, problems are easily fixed by explicitly converting array scalars to Python scalars, using the corresponding Python type function (e.g., int, float, complex, str, unicode).

因此,在大多数情况下,可能根本不需要转换,可以直接使用数组标量。效果应该与使用Python scalar相同:

>>> np.issubdtype(np.int64, int)
True
>>> np.int64(0) == 0
True
>>> np.issubdtype(np.float64, float)
True
>>> np.float64(1.1) == 1.1
True

但是,如果出于某种原因,需要显式转换,则使用相应的Python内置函数是正确的方法。正如另一个答案所示,它也比数组标量item()方法快。

我认为你可以像这样写一般类型的转换函数:

import numpy as np

def get_type_convert(np_type):
   convert_type = type(np.zeros(1,np_type).tolist()[0])
   return (np_type, convert_type)

print get_type_convert(np.float32)
>> (<type 'numpy.float32'>, <type 'float'>)

print get_type_convert(np.float64)
>> (<type 'numpy.float64'>, <type 'float'>)

这意味着没有固定的列表,您的代码将扩展到更多类型。