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.
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()
.
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)
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'>}
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.
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'>
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.
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]]
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}
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'>
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:
npValue.item()
npValue.astype(float)
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.
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.