2012-02-26 10 views
109

Jeśli mam numpy dtype, w jaki sposób automatycznie przekonwertować go na najbliższy typ danych Pythona? Na przykład,Konwersja numpy dtypes na rodzime typy pythonów

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

mógłbym spróbować wymyślić mapowanie wszystkich tych przypadkach, ale nie numpy zapewnić pewne automatyczny sposób konwertowania jego dtypes w najbliższych możliwych rodzimych typów Pythona? To odwzorowanie nie musi być wyczerpujące, ale powinno przekonwertować wspólne dtypes, które mają bliskiego pythonowego odpowiednika. Myślę, że to już zdarza się gdzieś w numpy.

Odpowiedz

149

Zastosowanie albo a.item() lub np.asscalar(a) konwertować większość wartości NumPy do natywnego typu Python:

import numpy as np 
# examples using a.item() 
type(np.float32(0).item()) # <type 'float'> 
type(np.float64(0).item()) # <type 'float'> 
type(np.uint32(0).item()) # <type 'long'> 
# examples using np.asscalar(a) 
type(np.asscalar(np.int16(0))) # <type 'int'> 
type(np.asscalar(np.cfloat(0))) # <type 'complex'> 
type(np.asscalar(np.datetime64(0, 'D'))) # <type 'datetime.datetime'> 
type(np.asscalar(np.timedelta64(0, 'D'))) # <type 'datetime.timedelta'> 
... 

Czytaj więcej in the NumPy manual. Dla ciekawskich, aby zbudować tabelę konwersji do systemu:

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 

Istnieje kilka rodzajów NumPy które nie mają rodzimy odpowiednik Python w niektórych systemach, w tym: clongdouble, clongfloat, complex192, complex256, float128, longcomplex , longdouble i longfloat. Należy je przekonwertować na najbliższy odpowiednik NumPy przed użyciem asscalar.

9

Jak o:

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'>} 
+1

Podaję ten rodzaj rozwiązania jako możliwość na końcu mojego pytania. Ale szukam rozwiązania systemowego, a nie twardego, które obejmuje tylko kilka przypadków. Na przykład, jeśli numpy doda więcej dtypów w przyszłości, twoje rozwiązanie zostanie przerwane.Nie jestem zadowolony z tego rozwiązania. – conradlee

+0

Liczba możliwych dtypów jest nieograniczona. Rozważmy 'np.dtype ('mint8')' dla dowolnej liczby całkowitej dodatniej 'm'. Nie może istnieć wyczerpujące mapowanie. (Nie wierzę też, że istnieje funkcja wbudowana do wykonania tej konwersji dla ciebie. Mógłbym się mylić, ale nie sądzę) :)) – unutbu

+2

Python mapuje numpy dtypes do typów Pythona, nie jestem pewien jak, ale Chciałbym użyć dowolnej metody. Myślę, że to musi się zdarzyć, aby pozwolić, na przykład, na mnożenie (i inne operacje) między numpy dtypes i typami Pythona. Sądzę, że ich metoda nie mapuje w sposób wyczerpujący wszystkich możliwych typów numpy, ale przynajmniej te najczęstsze, w których ma to sens. – conradlee

4

myślę, że można po prostu napisać ogólną funkcję typ konwersji tak:

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

Oznacza to, że nie ma ustalonej listy i Twój kod będzie skalować z kilku rodzajów.

+0

Czy wiesz, gdzie znajduje się kod źródłowy dla części metody tolist(), która mapuje typy numpy na typy python? Rzuciłem szybkie spojrzenie, ale nie mogłem go znaleźć. – conradlee

+0

To jest trochę hack, co robię, to generowanie 'numpy.ndarray' z 1 zerem za pomocą' zeros() 'i wywoływanie' ndarrays' 'tolist()' do konwersji na typy natywne . Raz w typach natywnych pytam o typ i zwracam go. 'tolist()' jest zapowiedzią 'ndarray' –

+0

Tak, widzę, że - działa to, czego chcę, więc zaakceptowałem twoje rozwiązanie. Zastanawiam się jednak, w jaki sposób tolist() wykonuje swoją pracę, decydując, jaki typ wrzucić, i nie jestem pewien, jak znaleźć źródło. – conradlee

18

znalazłem się mieszane zestaw typów numpy i standardowy python. jak wszystkie NumPy rodzaje wywodzą się z numpy.generic, oto jak można przekonwertować wszystko do Python standardowe typy:

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

Można również zadzwonić do item() method obiektu, który chcesz przekonwertować:

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

numpy utrzymuje, że informacje zawarte w mapowaniu narażony typeDict więc można zrobić coś jak poniżej ::

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

Jeśli chcesz rzeczywistej pyt hon typy zamiast ich nazwy, można to zrobić ::

>>> {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} 
3

Jeśli chcesz przekonwertować (numpy.array LUB numpy skalar lub natywne typu lub numpy.darray) z natywnym typu można po prostu zrobić:

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

tolist skonwertuje skalar lub tablicę na macierzysty typ python. Domyślna funkcja lambda dba o przypadek, w którym wartość jest już natywna.

Powiązane problemy