programing

numpy dtype을 네이티브 python 형식으로 변환하는 중

bestcode 2022. 9. 16. 00:05
반응형

numpy dtype을 네이티브 python 형식으로 변환하는 중

numpy dtype이 있는 경우 가장 가까운 python 데이터 타입으로 자동 변환하려면 어떻게 해야 합니까?예를들면,

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

이 모든 경우의 매핑을 생각해 낼 수 있습니다만, numpy는 dtype을 가능한 가장 가까운 네이티브 Python 타입으로 자동 변환하는 방법을 제공하고 있습니까?이 매핑은 완전할 필요는 없지만 python 아날로그에 가까운 공통 dtype을 변환해야 합니다.내 생각에 이것은 이미 어딘가에서 일어나고 있는 것 같다.

대부분의 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 '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'>
...

(다른 방법은 입니다만, 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

일부 시스템에는 다음과 같은 네이티브 Python이 없는 NumPy 유형이 있습니다.clongdouble,clongfloat,complex192,complex256,float128,longcomplex,longdouble그리고.longfloat사용하기 전에 가장 가까운 NumPy로 변환해야 합니다..item().

모든 numpy 타입이 에서 유래하듯이 numpy 타입과 표준 python의 혼합 세트를 가지고 있는 것을 발견했다.numpy.generic모든 것을 python 표준 타입으로 변환하는 방법은 다음과 같습니다.

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

(numpy.array OR numpy scalar OR native type OR numpy.darray)를 네이티브타입으로 변환하려면 다음 절차를 수행합니다.

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

tolist는 스칼라 또는 어레이를 python 네이티브 타입으로 변환합니다.기본 람다 함수는 값이 이미 기본인 경우를 처리합니다.

tolist()이를 실현하기 위한 보다 일반적인 접근방식입니다.모든 원시 d타입에서 동작하며 배열 또는 매트릭스에서도 동작합니다.

원시 유형에서 호출된 경우 실제로 목록을 생성하지 않습니다.

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

그럼 어떻게 해?

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

변환할 객체의 메서드를 호출할 수도 있습니다.

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

너무 늦게 와서 미안한데, 내가 지금 보고 있는 건numpy.float64일반 Python으로 변경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)훨씬 빠른 것 같아요.

그냥 일반형 변환함수라고 쓰면 될 것 같아요.

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는 다음과 같이 노출되는 매핑에서 해당 정보를 보유합니다.typeDict을 사용하다

>>> import __builtin__ as builtins  # if python2
>>> import builtins                 # if python3

그 후:

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

이름이 아닌 실제 python 유형을 원하는 경우 다음을 수행할 수 있습니다.

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

내 접근 방식은 다소 강압적이지만 모든 경우에 잘 맞는 것 같다.

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

자동 변환이 필요 없고 값의 numpy dtype을 알고 있는 사용자를 위해 어레이 스칼라에 대한 참고 사항:

배열 스칼라는 Python 스칼라와 다르지만 대부분 서로 교환하여 사용할 수 있습니다(기본적으로 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()★★★★★★ 。

numpy 유형의 배열 list_numpy_number가 있는 경우 다음을 수행합니다.

list_native_numbers = [i.item() for i in list_numpy_numbers]

1개의 유닛 데이터 오브젝트 대신 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

그러나 대용량 데이터 프레임을 처리할 때는 몇 분 정도 걸립니다.저도 좀 더 효율적인 해결책을 찾고 있습니다.더 나은 답이 있길 바라.

언급URL : https://stackoverflow.com/questions/9452775/converting-numpy-dtypes-to-native-python-types

반응형