NumPy 배열의 적절한 유형 변환


127

의 NumPy 배열이 주어지면 int32어떻게 float32 제자리 로 변환 합니까? 기본적으로 저는하고 싶습니다

a = a.astype(numpy.float32)

배열을 복사하지 않고. 그건 크다.

이 작업을 수행하는 이유는의 계산을위한 두 가지 알고리즘이 있기 때문입니다 a. 그들 중 하나는의 배열을 int32반환하고 다른 하나는의 배열을 반환합니다 float32(이것은 두 가지 알고리즘에 내재되어 있습니다). 모든 추가 계산에서는이 a배열이로 가정합니다 float32.

현재 via라는 C 함수에서 변환을 수행합니다 ctypes. 파이썬에서 이것을 할 수있는 방법이 있습니까?


를 사용하는 ctypes것은 "Python에서"를 사용하는 것만 큼을 사용 numpy합니다. :)
— Karl Knechtel

3
@Karl : 아니요. C 함수를 직접 코딩하고 컴파일해야하기 때문입니다.
— Sven Marnach

아, 알겠습니다 아마 당신은 이것에 대해 SOL 일 것입니다.
— Karl Knechtel

3
@Andrew : 사본을 반환하는지 확인하는 방법에는 여러 가지가 있습니다. 그들 중 하나는 문서 를 읽는 것입니다 .
— Sven Marnach

1
제자리는 단순히 "원래 어레이와 동일한 메모리 사용"을 의미합니다. 허용 된 답변을 살펴보십시오. 마지막 부분은 새 값이 실제로 동일한 메모리를 덮어 썼음을 보여줍니다.
— Sven Marnach

답변:


110

다른 dtype으로 뷰를 만든 다음 뷰에 적절한 위치로 복사 할 수 있습니다.

import numpy as np
x = np.arange(10, dtype='int32')
y = x.view('float32')
y[:] = x

print(y)

수확량

array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.], dtype=float32)

변환이 제대로 이루어 졌음을 나타내려면 에서 x 에서 y변경으로 복사하십시오 x.

print(x)

인쇄물

array([         0, 1065353216, 1073741824, 1077936128, 1082130432,
       1084227584, 1086324736, 1088421888, 1090519040, 1091567616])

26
다른 바이트 크기의 dtype (예 : 32 ~ 16 비트) 사이의 변환을 원하는 (예 : 나와 같은) 참고 사항 : y.size <> x.size 때문에이 방법은 실패합니다. 일단 생각하면 논리 :-(
— Juh_

이 솔루션이 일부 이전 버전의 Numpy에서 작동 했습니까? np.arange(10, dtype=np.int32).view(np.float32)Numpy 1.8.2에서 할 때 array([ 0.00000000e+00, 1.40129846e-45, ... [snip] ... 1.26116862e-44], dtype=float32).
— Bas Swinckels

3
@BasSwinckels : 예상됩니다. 할당 할 때 변환이 발생합니다 y[:] = x.
— unutbu 2016 년

itemsize (비트의 수)에 대해 이루어진 점을 명확히하기 위해 원래의 답으로 불리며 @Juh_ 예 : a = np.arange(10, dtype='float32'); b = a[::-1]; c = np.vstack((a,b)); d = c.view('float64')이 코드보다 오히려 float64 20 10 10 + 10 float32 결과를 얻어
— dcanelhas

1
이 적절한 변경은 메모리 사용을 절약 할 수 있지만 간단한 x.astype(float)변환 보다 속도가 느립니다 . 스크립트가 MemoryError와 경계를 이루지 않는 한 권장하지 않습니다.
— hpaulj

158

업데이트 :이 기능은 가능한 경우 복사를 피 하므로이 질문에 대한 정답은 아닙니다. unutbu의 대답 이 옳습니다.


a = a.astype(numpy.float32, copy=False)

numpy astype에는 복사 플래그가 있습니다. 왜 우리는 그것을 사용해서는 안됩니까?


14
이 매개 변수가 NumPy 릴리스에서 지원되면 물론 사용할 수 있지만 현재는 개발 지점에서만 사용할 수 있습니다. 그리고 내가이 질문을 할 당시에는 전혀 존재하지 않았습니다.
— Sven Marnach

2
@SvenMarnach 이제 내 버전 (1.7.1) 이상에서 지원됩니다.
— PhilMacKay

최신 numpy 버전으로 python3.3에서 완벽하게 작동하는 것 같습니다.
— CHM

1
나는 이것이 a = a.view ((float, len (a.dtype.names)))보다 약 700 배 느리다는 것을 알았습니다.
— JJ

14
copy 플래그는 사본없이 변경을 수행 할 수 있으면 사본없이 수행된다는 것만 나타냅니다. 그러나 유형이 다르면 항상 복사됩니다.
— coderforlife

14

다음과 같이 변환하지 않고 배열 유형을 변경할 수 있습니다.

a.dtype = numpy.float32

그러나 먼저 모든 정수를 해당 부동 소수점으로 해석되는 것으로 변경해야합니다. 이를 수행하는 매우 느린 방법은 다음 struct과 같이 파이썬 모듈 을 사용하는 것입니다 .

def toi(i):
    return struct.unpack('i',struct.pack('f',float(i)))[0]

... 어레이의 각 멤버에 적용됩니다.

그러나 아마도 가장 빠른 방법은 numpy의 ctypeslib 도구를 사용하는 것입니다.

- 편집하다 -

ctypeslib가 작동하지 않는 것 같으므로 일반적인 numpy.astype방법으로 변환을 진행하지만 메모리 제한 내에있는 블록 크기로 진행합니다.

a[0:10000] = a[0:10000].astype('float32').view('int32')

... 완료되면 dtype을 변경하십시오.

다음은 호환 가능한 dtype에 대한 작업을 수행하고 (동일한 크기의 항목이있는 dtype에 대해서만 작동) 블록 크기를 사용자가 제어 할 수있는 임의의 모양 배열을 처리하는 함수입니다.

import numpy

def astype_inplace(a, dtype, blocksize=10000):
    oldtype = a.dtype
    newtype = numpy.dtype(dtype)
    assert oldtype.itemsize is newtype.itemsize
    for idx in xrange(0, a.size, blocksize):
        a.flat[idx:idx + blocksize] = \
            a.flat[idx:idx + blocksize].astype(newtype).view(oldtype)
    a.dtype = newtype

a = numpy.random.randint(100,size=100).reshape((10,10))
print a
astype_inplace(a, 'float32')
print a

1
답변 주셔서 감사합니다. 솔직히, 이것이 큰 배열에 매우 유용하다고 생각하지 않습니다 . 너무 느립니다. 배열의 데이터를 다른 유형으로 재 해석하는 것은 쉽습니다 (예 : 호출) a.view(numpy.float32). 어려운 부분은 실제로 데이터를 변환하는 것입니다. numpy.ctypeslib실제로 데이터를 변환하는 것이 아니라 데이터를 재 해석하는 데 도움이됩니다.
— Sven Marnach

확인. 메모리 / 프로세서 제한이 무엇인지 잘 모르겠습니다. 내 편집을 참조하십시오.
— Paul

업데이트 해 주셔서 감사합니다. 현재 NumPy 인터페이스로 얻을 수있는 최선의 방법은 블록 방식으로하는 것이 좋습니다. 그러나이 경우 아마도 현재 ctypes 솔루션을 고수 할 것입니다.
— Sven Marnach

-1
import numpy as np
arr_float = np.arange(10, dtype=np.float32)
arr_int = arr_float.view(np.float32)

view () 및 매개 변수 'dtype'을 사용하여 배열을 변경하십시오.


문제의 목표 는 데이터 를 실제로 변환 하는 것이 었 습니다. 마지막 줄의 유형을로 수정하면 int이 답변은 기존 데이터를 다른 유형으로 만 재 해석합니다. 이것은 내가 요구 한 것이 아닙니다.
— Sven Marnach

무슨 소리 야? dtype은 메모리에있는 데이터의 모양 일 뿐이며 실제로 작동하지만 np.astype에서는 매개 변수 'casting'이 변환 방법 기본값 'unsafe'를 제어 할 수 있습니다.
— 蒋志强

예, 첫 번째 답변에 동의합니다. 그러나 arr_.astype (new_dtype, copy = False)는 여전히 새로 할당 된 배열을 반환합니다. 어떻게 만족하는 dtype, order및 subok배열의 복사본을 반환하는 요구 사항을? 나는 그것을 해결하지 못한다.
— 蒋志强

-5

이것을 사용하십시오 :

In [105]: a
Out[105]: 
array([[15, 30, 88, 31, 33],
       [53, 38, 54, 47, 56],
       [67,  2, 74, 10, 16],
       [86, 33, 15, 51, 32],
       [32, 47, 76, 15, 81]], dtype=int32)

In [106]: float32(a)
Out[106]: 
array([[ 15.,  30.,  88.,  31.,  33.],
       [ 53.,  38.,  54.,  47.,  56.],
       [ 67.,   2.,  74.,  10.,  16.],
       [ 86.,  33.,  15.,  51.,  32.],
       [ 32.,  47.,  76.,  15.,  81.]], dtype=float32)

5
그게 사본이 아닙니까? 확인하고 조금 더 설명해 주시겠습니까?
— Michele d' Amico

-5

a = np.subtract(a, 0., dtype=np.float32)


1
이 코드 스 니펫이 해결책이 될 수 있지만 설명을 포함하면 게시물의 품질을 향상시키는 데 실제로 도움이됩니다. 앞으로 독자에게 질문에 대한 답변을 제공하고 있으며 해당 사람들이 귀하의 코드 제안 이유를 모를 수도 있습니다.
— Sebastialonso

이것이 적절한 전환 이되어야하는 이유는 무엇 입니까? numpy.subtract사본을 반환하지 않습니까? a다른 이름 의 데이터에 재사용 된 이름 만 ... 이것에 대해 틀렸다면 설명해주세요.
— koffein

이것을 지적 해 주셔서 감사합니다. 당신이 옳은 것 같습니다-사본이 만들어집니다.
— MIO
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.