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, ordersubok배열의 복사본을 반환하는 요구 사항을? 나는 그것을 해결하지 못한다.
蒋志强

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