web-dev-qa-db-fra.com

Conversion de types numpy en types python natifs

Si j'ai un type numpy, comment puis-je le convertir automatiquement en son type de données le plus proche python? Par exemple,

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

Je pourrais essayer de faire un mappage de tous ces cas, mais numpy fournit-il un moyen automatique de convertir ses types types en types natifs python les plus proches possibles? Ce mappage n'a pas besoin d'être exhaustif, mais il doit convertir les types communs qui ont un analogue proche python. Je pense que cela se produit déjà quelque part numpy.

190
conradlee

Utilisez val.item() pour convertir la plupart des valeurs NumPy en un type natif 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 'long'>
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'>
...

(Une autre méthode est np.asscalar(val) , mais il est déconseillé depuis NumPy 1.16).


Pour les curieux, construire une table de conversions de scalaires de tableaux NumPy pour votre système:

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

Il existe quelques types NumPy qui n'ont pas d'équivalent natif Python sur certains systèmes, notamment: clongdouble, clongfloat, complex192, complex256, float128, longcomplex, longdouble et longfloat. Ceux-ci doivent être convertis en leur équivalent NumPy le plus proche avant d'utiliser .item().

256
Mike T

je me suis retrouvé avec un ensemble mixte de types numpy et de python standard. comme tous les types numpy proviennent de numpy.generic, voici comment vous pouvez tout convertir en python types standard:

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

Que diriez-vous:

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'>}
10
unutbu

Si vous voulez convertir (numpy.array OR numpy scalaire OR type natif OR numpy.darray) en type natif, vous pouvez simplement faire:

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

tolist convertira votre scalaire ou votre tableau en python type natif. La fonction lambda par défaut prend en charge le cas où la valeur est déjà native.

9
v.thorey

Vous pouvez également appeler la méthode item() de l'objet que vous souhaitez convertir:

>>> from numpy import float32, uint32
>>> type(float32(0).item())
<type 'float'>
>>> type(uint32(0).item())
<type 'long'>
7

Je pense que vous pouvez simplement écrire une fonction de conversion de type général comme ceci:

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

Cela signifie qu'il n'y a pas de listes fixes et que votre code évoluera avec plus de types.

6
Matt Alcock

tolist() est une approche plus générale pour y parvenir. Cela fonctionne dans n'importe quel type primitif et aussi dans les tableaux ou matrices.

En fait, je ne donne pas de liste si elle est appelée à partir de types primitifs:

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]]
6
Carlos Santos

numpy conserve ces informations dans un mappage exposé sous la forme typeDict afin que vous puissiez faire quelque chose comme ce qui suit:

>>> import __builtin__
>>> import numpy as np
>>> {v: k for k, v in np.typeDict.items() if k in dir(__builtin__)}
{numpy.object_: 'object',
 numpy.bool_: 'bool',
 numpy.string_: 'str',
 numpy.unicode_: 'unicode',
 numpy.int64: 'int',
 numpy.float64: 'float',
 numpy.complex128: 'complex'}

Si vous voulez les types python réels plutôt que leurs noms, vous pouvez faire ::

>>> {v: getattr(__builtin__, k) for k, v in np.typeDict.items() if k in vars(__builtin__)}
{numpy.object_: object,
 numpy.bool_: bool,
 numpy.string_: str,
 numpy.unicode_: unicode,
 numpy.int64: int,
 numpy.float64: float,
 numpy.complex128: complex}
2
Meitham

Mon approche est un peu énergique, mais semble jouer à Nice dans tous les cas:

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])

Usage:

>>> 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'>
1
Simon Streicher

Désolé de venir en retard en partie, mais je cherchais un problème de conversion de numpy.float64 en normal Python float uniquement. J'ai vu 3 façons de faire ça:

  1. npValue.item()
  2. npValue.astype(float)
  3. float(npValue)

Voici les timings pertinents de 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

Il semble que float(npValue) semble beaucoup plus rapide.

1
gt6989b

Traduisez l'intégralité de ndarray à la place d'un objet de données unitaire:

def trans(data):
"""
translate numpy.int/float into python native data type
"""
result = []
for i in data.index:
    # i = data.index[0]
    d0 = data.iloc[i].values
    d = []
    for j in d0:
        if 'int' in str(type(j)):
            res = j.item() if 'item' in dir(j) else j
        Elif 'float' in str(type(j)):
            res = j.item() if 'item' in dir(j) else j
        else:
            res = j
        d.append(res)
    d = Tuple(d)
    result.append(d)
result = Tuple(result)
return result

Toutefois, la manipulation de grandes trames de données prend quelques minutes. Je cherche aussi une solution plus efficace. J'espère une meilleure réponse.

0
Qinhong Ma