numpy dtype을 기본 파이썬 유형으로 변환


238

numpy dtype이 있으면 가장 가까운 python 데이터 유형으로 자동 변환하는 방법은 무엇입니까? 예를 들어

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

이 모든 경우의 매핑을 생각해 볼 수는 있지만 numpy는 dtype을 가장 가까운 원시 파이썬 유형으로 자동 변환하는 방법을 제공합니까? 이 매핑은 철저 할 필요는 없지만 가까운 파이썬 아날로그를 가진 일반적인 dtype을 변환해야합니다. 나는 이것이 이미 어딘가에 있다고 생각합니다.

답변:


325

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

(또 다른 방법은 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와 유형이있다 : clongdouble, clongfloat, complex192, complex256, float128, longcomplex, longdoublelongfloat. 사용하기 전에 가장 가까운 NumPy로 변환해야합니다 .item().


팬더 (0.23.0)를 사용하고 있습니다. 적어도 그 버전의 경우 np.str에는 .item () 메서드가 없으므로 .item ()을 try 블록 안에 래핑하는 것이 유일한 방법이었습니다.
Robert Lugg

3
@RobertLugg np.str는 Numpy 유형이 아니므 np.str is str로 표준 Python 유형의 별칭 일뿐입니다. 와 같은 np.float, np.int, np.bool, np.complex,와 np.object. Numpy 유형에는 후행이 있습니다 _(예 :) np.str_.
Mike T

이해 했어요. : 문제는 그래서 내가 할 수있는 "경우 좋은 될 것" np.float64(0).item()도하고 np.float(0).item(). 즉, 수행 할 작업이 알려진 .item()경우 단순히 동일한 값을 반환하더라도 메서드를 지원합니다 . 그렇게하면 .item()특별한 케이스없이 훨씬 더 많은 스칼라에 적용 할 수 있습니다 . 그대로, 병렬 구현 개념은 기본 구현으로 인해 다릅니다. 나는 이것이 왜되었는지 완전히 이해합니다. 그러나 라이브러리 사용자에게는 성가신 일입니다.
Robert Lugg

45

numpy 유형과 표준 파이썬이 혼합되어 있음을 발견했습니다. 모든 numpy 유형이에서 파생되었으므로 numpy.generic모든 것을 파이썬 표준 유형으로 변환하는 방법은 다음과 같습니다.

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

5
으로 허용 대답 노트 , NumPy와 1.16은 사용되지 않는 np.asscalar()방법. 왜? 아마 분명한 이유가 없을 것입니다. 10 년간의 상대적 안정성에도 불구하고 NumPy API는 현재 다운 스트림 애플리케이션의 지속적인 유지 보수를 요구하는 불안정한 이동 대상입니다. 적어도 그들은 지금 우리에게 item()방법 을 떠났습니다 .
Cecil Curry

asscalar 방법은 numpy v1.6 이후로 감가 상각되었습니다
Eswar

답변을 쉽게 바꿀 수 있으며 if isinstance(o, numpy.generic): return o.item() raise TypeError사용되지 않는 답변으로 다시 바뀝니다. D
Buggy

19

(numpy.array 또는 numpy 스칼라 OR 기본 유형 또는 numpy.darray) 기본 유형으로 변환하려면 다음을 수행하십시오.

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

tolist는 스칼라 또는 배열을 파이썬 기본 유형으로 변환합니다. 기본 람다 함수는 값이 이미 고유 한 경우를 처리합니다.


2
혼합 유형 (네이티브 및 비 네이티브)에 대한 가장 깔끔한 접근 방식! 그리고 궁금해하는 사람들에게는 tolist는 생각할 수있는 목록이 아닌 단일 값으로 호출 할 때 단일 값 (스칼라)을 반환합니다. 람다를 작성하는 가장 간단한 방법은 lambda: value입력을 원하지 않기 때문입니다.
fgblomqvist

getattr+ tolist콤보는 보편적 일뿐만 아니라 벡터화되어 있습니다! (unlinke .item ())
mirekphd

11

어때요 :

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
내 질문의 끝에서 그 유형의 솔루션을 가능성으로 언급합니다. 그러나 나는 단지 몇 가지 경우를 다루는 하드 코딩 된 솔루션보다는 체계적인 솔루션을 찾고 있습니다. 예를 들어, numpy가 나중에 더 많은 dtype을 추가하면 솔루션이 중단됩니다. 그래서 나는 그 해결책에 만족하지 않습니다.
conradlee

가능한 dtype의 수는 제한이 없습니다. np.dtype('mint8')양의 정수를 고려하십시오 m. 철저한 매핑이 불가능합니다. (나는 또한 당신을 위해이 변환을 수행하는 내장 함수가 있다고 생각하지 않습니다. 틀릴 수는 있지만 그렇게 생각하지 않습니다 :))
unutbu

2
파이썬은 numpy dtypes를 python 유형에 매핑합니다. 어떻게 잘 모르겠지만 그들이하는 모든 방법을 사용하고 싶습니다. 예를 들어 numpy dtype과 python 유형 사이의 곱셈 (및 기타 연산)을 허용해야한다고 생각합니다. 나는 그들의 방법이 가능한 모든 numpy 유형을 철저하게 매핑하지는 않지만 적어도 그것이 가장 적합한 유형을 매핑한다고 생각합니다.
conradlee

일관되게 작동하지 않습니다 >>> print([numpy.asscalar(x) for x in numpy.linspace(1.0, 0.0, 21)]) [1.0, 0.95, 0.9, 0.85, 0.8, 0.75, 0.7, 0.6499999999999999, 0.6, 0.55, 0.5, 0.44999999999999996, 0.3999999999999999, 0.35, 0.29999999999999993, 0.25, 0.19999999999999996, 0.1499999999999999, 0.09999999999999998, 0.04999999999999993, 0.0]. 모든 값이 올바르게 변환 된 것은 아닙니다.
Alex F

내 이전 의견에 따르면, 이상하게도 이것이 작동하지만 Numpy 기본 유형 대신 Python 기본 유형에 라운드를 넣어야합니다. >>> print([numpy.asscalar(round(x,2)) for x in numpy.linspace(1.0, 0.0, 21)]) [1.0, 0.95, 0.9, 0.85, 0.8, 0.75, 0.7, 0.65, 0.6, 0.55, 0.5, 0.45, 0.4, 0.35, 0.3, 0.25, 0.2, 0.15, 0.1, 0.05, 0.0]
Alex F

9

tolist()이를 달성하기위한보다 일반적인 접근 방식입니다. 모든 기본 dtype과 배열 또는 행렬에서도 작동합니다.

기본 유형에서 호출하면 실제로 목록을 생성하지 않습니다.

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

일반적인 유형 변환 함수를 다음과 같이 작성할 수 있다고 생각합니다.

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

이것은 고정 목록이 없으며 코드가 더 많은 유형으로 확장됨을 의미합니다.


numpy 유형을 python 유형으로 맵핑하는 tolist () 메소드의 일부에 대한 소스 코드의 위치를 ​​알고 있습니까? 빨리 보았지만 찾을 수 없었습니다.
conradlee

이것은 내가하고있는 약간의 해킹 numpy.ndarray으로 1을 사용하여 0을 생성하고 기본 유형으로 변환 zeros()하는 ndarrays tolist()함수를 호출합니다 . 네이티브 타입이라면 나는 타입을 반환하도록 요청합니다. tolist()ndarray
Matt Alcock

그래, 나는 그것을 ---- 나는 내가 원하는 것을 위해 일한다. 그래서 나는 당신의 해결책을 받아 들였다. 그러나 tolist ()가 어떤 유형으로 캐스트할지 결정하는 방법을 궁금해하며 소스를 찾는 방법을 잘 모르겠습니다.
conradlee

numpy.sourceforge.net/numdoc/HTML/numdoc.htm#pgfId-36588 은 함수가 문서화 된 곳입니다. 나는 inspect가 더 많은 정보를 찾을 수는 있지만 기쁨은 없다고 생각했습니다. 다음 단계에서는 github.com/numpy/numpy.git 을 복제 하고 실행 하려고했습니다 grep -r 'tolist' numpy. (여전히 진행, NumPy와 대규모입니다!)
매트 Alcock 씨

3

numpy는 typeDict다음과 같은 작업을 수행 할 수 있도록 노출 된 매핑에 해당 정보를 보유합니다.

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

이름 대신 실제 파이썬 유형을 원한다면 ::

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

늦게 와서 죄송하지만 numpy.float64일반 파이썬으로 float만 변환하는 문제를보고있었습니다 . 나는 그것을하는 세 가지 방법을 보았습니다.

  1. npValue.item()
  2. npValue.astype(float)
  3. float(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)훨씬 빠른 것 같다.


1

내 접근 방식은 약간 강력하지만 모든 경우에 훌륭하게 작동하는 것 같습니다.

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

나는 이것이 본질적으로 Matt Alcock의 대답과 동일하다는 것을 알았습니다.
사이먼 STREICHER

1

자동 변환이 필요하지 않고 값의 numpy dtype을 알고있는 사람들을위한 배열 스칼라에 대한 참고 사항 :

배열 스칼라는 Python 스칼라와 다르지만 대체로 상호 교환 하여 사용할 수 있습니다 (1 차 예외는 정수 배열 스칼라가 목록 및 튜플의 인덱스로 작동 할 수없는 v2.x 이전의 Python 버전의 경우). 코드에 스칼라의 특정 속성이 필요한 경우 또는 값이 Python 스칼라인지 여부를 구체적으로 검사하는 경우와 같은 일부 예외가 있습니다. 일반적으로, 대응하는 Python 유형 함수 (예 : int, float, complex, str, unicode)를 사용하여 배열 스칼라를 Python 스칼라로 명시 적으로 변환하여 문제를 쉽게 해결할 수 있습니다.

출처

따라서 대부분의 경우 변환이 전혀 필요하지 않을 수 있으며 배열 스칼라를 직접 사용할 수 있습니다. 효과는 Python 스칼라를 사용하는 것과 동일해야합니다.

>>> 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()방법 보다 빠릅니다 .


0

하나의 단위 데이터 객체 대신 전체 ndarray를 번역하십시오.

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

그러나 큰 데이터 프레임을 처리하는 데 몇 분이 걸립니다. 또한 더 효율적인 솔루션을 찾고 있습니다. 더 나은 답변을 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.