Coder Perfect

Numpy dtypes -> native Python types conversion

Problem

How can I convert a numpy dtype to the closest python data type automatically? As an example,

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

I could try to map all of these situations together, but does numpy have a built-in way of automatically converting its dtypes to the nearest native Python types? This mapping does not have to be thorough, but it should convert the most common dtypes to their Python equivalents. This, I believe, already occurs in numpy.

Asked by conradlee

Solution #1

To convert most NumPy values to a native Python type, use val.item():

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'>
...

(There is also np.asscalar(val), but it has been deprecated since NumPy 1.16.)

To create a table of NumPy array scalar conversions for your system, follow these steps:

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

clongdouble, clongfloat, complex192, complex256, float128, longcomplex, longdouble, and longfloat are several NumPy types that don’t have a native Python equivalent on some systems. Before using.item, they must be translated to their closest NumPy counterpart ().

Answered by Mike T

Solution #2

I discovered that I had a mixture of numpy types and normal python. Because all numpy types are descended from numpy.generic, here’s how to convert everything to ordinary Python types:

if isinstance(obj, numpy.generic):
    return numpy.asscalar(obj)

Answered by tm_lv

Solution #3

You can simply do the following to convert (numpy.array OR numpy scalar OR native type OR numpy.darray) TO native type:

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

Your scalar or array will be converted to a Python native type using tolist. When value is already native, the default lambda function takes care of it.

Answered by v.thorey

Solution #4

The function tolist() is a more general way to accomplish this. It can be used in any primitive dtype, as well as arrays and matrices.

When called from primitive types, it does not truly return a list:

numpy == 1.15.2

>>> import numpy as np

>>> np_float = np.float64(1.23)
>>> print(type(np_float), np_float)
<class 'numpy.float64'> 1.23

>>> listed_np_float = np_float.tolist()
>>> print(type(listed_np_float), listed_np_float)
<class 'float'> 1.23

>>> np_array = np.array([[1,2,3.], [4,5,6.]])
>>> print(type(np_array), np_array)
<class 'numpy.ndarray'> [[1. 2. 3.]
 [4. 5. 6.]]

>>> listed_np_array = np_array.tolist()
>>> print(type(listed_np_array), listed_np_array)
<class 'list'> [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]

Answered by Carlos Santos

Solution #5

How about:

In [51]: dict([(d, type(np.zeros(1,d).tolist()[0])) for d in (np.float32,np.float64,np.uint32, np.int16)])
Out[51]: 
{<type 'numpy.int16'>: <type 'int'>,
 <type 'numpy.uint32'>: <type 'long'>,
 <type 'numpy.float32'>: <type 'float'>,
 <type 'numpy.float64'>: <type 'float'>}

Answered by unutbu

Post is based on https://stackoverflow.com/questions/9452775/converting-numpy-dtypes-to-native-python-types