NumPy 배열


https://webnautes.tistory.com/1176

1.1. NumPy 배열(ndarray)이란?
1.2. NumPy 배열과 파이썬 리스트 비교
1.3. NumPy 배열과 파이썬 리스트 성능 비교
1.4. 차원 개수와 차원 크기
1.5. 1차원 배열 사용시 주의할 점
1.6. NumPy 배열의 원소 접근 방법
1.7. print 함수로 NumPy 배열 출력시 시각화 방법
1.8. NumPy 배열 데이터 타입

1.1. NumPy 배열(ndarray)이란?

NumPy 배열는 N 차원 배열(N-dimensional array) 객체로 파이썬의 리스트와 달리 같은 타입의 데이터만 저장할 수 있습니다.

같은 타입만 저장할 수 있기 때문에 NumPy 배열은 호모지니어스(Homogeneous)합니다.
호모지니어스 개념은 아래 블로그에 설명이 잘되어있습니다.

동차, Homogeneous http://tedder.tistory.com/104

배열의 모든 원소는 같은 타입이므로 같은 크기의 메모리 블록을 차지합니다.
각 블록이 해석되는 방법은 별도의 데이터 타입 객체(numpy.dtype 클래스의 인스턴스)에 의해서 지정됩니다.  

1.2. NumPy 배열과 파이썬 리스트 비교

NumPy 배열은 numpy.array 함수를 사용하여 생성할 수 있으며 파이썬 리스트처럼 인덱스를 사용하여 배열의 원소에 접근할 수 있습니다.
파이썬의 리스트 타입과 비교하며 자세히 살펴보겠습니다.

import numpy as np # numpy 모듈을 가져올 때 보통 np라는 이름을 붙여 사용합니다.


# 괄호 안에 데이터들을 콤마로 구분 입력한 것을 list 함수의 아규먼트로 사용하여 리스트를 생성합니다.
A = list([1, 'ABC', 0.1])
print("A = ", A, " type = ", type(A), "\n")
# 출력해보면 대괄호 안에 원소들이 콤마로 구분되어 있으며 타입은 list 클래스의 객체입니다.
# A =  [1, 'ABC', 0.1]  type = <class 'list'>

# 0부터 시작하는 정수 인덱스 하나로 리스트의 모든 원소를 접근할 수 있습니다.
print("A[0] = ", A[0], " type = ", type(A[0]))
print("A[1] = ", A[1], " type = ", type(A[1]))
print("A[2] = ", A[2], " type = ", type(A[2]), "\n")
# 파이썬 리스트에서는 각각의 원소가 본래의 데이터 타입을 유지합니다.
# 각각의 원소는 파이썬 데이터 타입의 객체입니다.
# A[0] =  1 type = <class 'int'>
# A[1] =  ABC type =  <class 'str'>
# A[2] =  0.1 type =  <class 'float'>



# 파이썬 리스트나 파이썬 튜플을 ndarray.array 함수의 아규먼트로 사용하여 NumPy 배열을 생성합니다.
B = np.array([1, 2, 3])  # 또는 B = np.array((1, 2, 3))
print("B = ", B, " type =", type(B), " B.dtype = ", B.dtype, "\n")
# NumPy 배열은 같은 데이터 타입을 원소로 하기 때문에 배열 데이터 타입 속성(dtype)을 가집니다.
# 파이썬 리스트와 동일하게 대괄호 안에 원소들이 출력되지만 콤마가 아닌 빈칸으로 구분되며 numpy.ndarray 클래스의 객체입니다.
# B =  [1 2 3]  type = <class 'numpy.ndarray'>  B.dtype = int32

# 파이썬 리스트처럼 0부터 시작하는 정수 인덱스 하나로 배열의 모든 원소를 접근할 수 있습니다.
print("B[0] = ", B[0], " type = ", type(B[0]), " dtype = ", B[0].dtype)
print("B[1] = ", B[1], " type = ", type(B[1]), " dtype = ", B[1].dtype)
print("B[2] = ", B[2], " type = ", type(B[2]), " dtype = ", B[2].dtype, "\n")
# 파이썬 리스트와 달리 모든 원소의 데이터 타입은 동일합니다.
# 각각의 원소는 NumPy 데이터 타입의 객체입니다.
# 원소도 배열 데이터 타입 속성(dtype)을 가지며 NumPy 배열과 타입이 동일합니다.
# B[0] =  1 type = <class 'numpy.int32'>  dtype = int32
# B[1] =  2 type = <class 'numpy.int32'>  dtype = int32
# B[2] =  3 type = <class 'numpy.int32'>  dtype = int32


# NumPy 배열에서도 파이썬 리스트처럼 여러가지 타입의 데이터를 입력할 수는 있습니다.
C = np.array(list([1, 'ABC', 0.1]))

print("C = ", C, " type =", type(C), " C.dtype = ", C.dtype, "\n")
# 하지만 출력해보면 유니코드 문자열 타입으로 통일된 것을 확인할 수 있습니다.
# C =  ['1' 'ABC' '0.1']  type = <class 'numpy.ndarray'>  C.dtype = <U11

print("C[0] = ", C[0], " type = ", type(C[0]), " dtype = ", C[0].dtype)
print("C[1] = ", C[1], " type = ", type(C[1]), " dtype = ", C[1].dtype)
print("C[2] = ", C[2], " type = ", type(C[2]), " dtype = ", C[2].dtype, "\n")
# 모든 원소가 유니코드 문자열 타입으로 변경되었습니다.
# C[0] =  1 type = <class 'numpy.str_'>  dtype = <U1
# C[1] =  ABC type =  <class 'numpy.str_'>  dtype = <U3
# C[2] =  0.1 type =  <class 'numpy.str_'>  dtype = <U3



# NumPy 배열의 원소값을 변경하는 방법도 파이썬 리스트와 동일합니다.
A[0] = 10000  # 파이썬 리스트
B[0] = 10000  # NumPy 배열

print("A = ", A)
print("B = ", B)
# A =  [10000, 'ABC', 0.1]
# B =  [10000    2 3]

1.3. NumPy 배열과 파이썬 리스트 성능 비교

앞에서 본 것처럼 NumPy 배열과 파이썬 리스트의 사용법은 거의 동일합니다.
하지만 NumPy 배열이 좀 더 효율적으로 메모리에 데이터를 저장하기 때문에 빠른 연산이 가능합니다.

같은 범위의 정수에 대해서 제곱을 계산결과를 비교해보았습니다.

import timeit


# 파이썬 리스트
print(timeit.timeit('[ i**2 for i in A]', setup='A=range(100)'))
# 42.39019135422791

# NumPy 배열
print(timeit.timeit('B**2', setup='import numpy as np;B=np.arange(100)'))
# 0.9117699142778122

NumPy 배열을 사용한 경우가  훨씬 빠른 것을 볼 수 있습니다.
왜냐면 좀 더 효율적으로 계산을 하기 때문입니다.  

파이썬 리스트의 경우에는 루프를 사용하여 리스트의 원소를 하나씩  접근하여 계산을 해야 합니다.
반면 NumPy 배열의 경우에는 벡터화된 산술 연산이 가능하기 때문에 루프 없이 스칼라 계산(1+2)하듯이 두 배열을 연산(A+B)할 수 있습니다.

1.4. 차원 개수와 차원 크기  

numpy.array 함수의 아규먼트로 사용되는 리스트 또는 튜플을 중첩하면  2차원 이상의 배열을 만들 수 있습니다.

1차원 배열을 만들기 위한 아규먼트는 데이터를 원소로 하는 리스트입니다.
[ 1, 2, 3, 4 ]  

2차원 배열을 만들기 위한 아규먼트는 1차원 리스트를 원소로 하는 리스트입니다.
[ [1, 2, 3, 4],  [4, 5, 6, 7],  [8, 9, 10, 11] ]

3차원 배열을 만들기 위한 아규먼트는 2차원 리스트를 원소로 하는 리스트입니다.
[ [[1, 2, 3, 4], [4, 5, 6, 7], [8, 9, 10, 11]], [[12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]]  ]

NumPy 배열의 차원 개수와 원소 개수는 ndarray.shape 속성을 사용하여 정의합니다.
shape 속성은 튜플로 출력되는데 원소 개수가 NumPy 배열의 차원 개수이며,  각 원소값이 각 차원의 크기입니다.
차원 개수만 확인할 수 있는 ndarray.ndim 속성도 있습니다.

import numpy as np


# 1차원 NumPy 배열
A = np.array([1, 2, 3, 4])
print("A.ndim = ", A.ndim)  # ndarray.ndim 속성은 배열의 차원 개수를 리턴합니다.
print("A.shape = ", A.shape)  # ndarray.shape 속성은 배열의 각 차원 크기를 튜플로 리턴합니다.
print("A  = ", A)
print("\n")
# 1차원 배열의 경우 차원이 한 개입니다.
# A.ndim =  1
# 첫번째 차원의 크기만 출력됩니다.
# A.shape =  (4,)

# 1차원 배열을 출력해보면 대괄호 사이에 원소가 공백으로 구분되어 첫번째 차원 크기(4개)만큼 출력됩니다.
# A  = [1 2 3 4]


# 2차원 NumPy 배열
B = np.array([ [1, 2, 3, 4], [4, 5, 6, 7], [8, 9, 10, 11] ] )
print("B.ndim = ", B.ndim)
print("B.shape = ", B.shape)
print("B  = \n", B)
print("\n")
# 2차원 배열의 경우 차원이 두 개입니다.
# B.ndim =  2
# 첫번째 차원의 크기, 두번째 차원의 크기 순으로 출력됩니다.
# B.shape =  (3, 4)

# 2차원 배열을 출력해보면 대괄호 사이에 1차원 배열이 줄단위로 구분되어 첫번째 차원 크기(3개)만큼 출력됩니다.
# 1차원 배열에는 두번째 차원 크기(4개)만큼 원소가 포함되어 있습니다.
# B  =
#  [[ 1  2 3 4]
#  [ 4  5 6 7]
#  [ 8  9 10 11]]


# 3차원 NumPy 배열
C = np.array([ [[1, 2, 3, 4], [4, 5, 6, 7], [8, 9, 10, 11]], [[12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]]  ])
print("C = \n", C)
print("C.ndim = ", C.ndim)
print("C.shape = ", C.shape)
# 3차원 배열의 경우 차원이 세 개입니다.
# C.ndim =  3
# 첫번째 차원의 크기, 두번째 차원의 크기, 세번째 차원의 크기 순으로 출력됩니다.
# C.shape =  (2, 3, 4)

# 3차원 배열을 출력해보면 대괄호에 두 개의 2차원 배열이 빈 줄로 구분되어 첫번째 차원 크기(2개)만큼 출력됩니다.
# 2차원 배열에는 각각 두번째 차원 크기(3개)만큼 1차원 배열이 줄단위 구분으로 포함되어 있습니다.
# 1차원 배열에는 각각 세번째 차원 크기(4개)만큼 원소가 포함되어 있습니다.
#
# C =
#  [[[ 1  2 3 4]
#   [ 4 5  6 7]
#   [ 8 9 10 11]]
#
#  [[12 13 14 15]
#   [16 17 18 19]
#   [20 21 22 23]]]

위 예에서 언급한 ndim, shape 외에도 NumPy 배열의 정보를 확인할 수 있는 속성들이 있습니다.
나머지 속성은 다음 링크에서 확인하세요.

1.5. 1차원 배열 사용시 주의할 점


앞에서 1차원 배열의 shape 속성을 출력해보았을 때, 두번째 원소 자리가 공백으로 남겨진 채 (4, )로 출력되었습니다.

A = np.array([1, 2, 3, 4])
print("A.shape = ", A.shape)
# A.shape =  (4,)

수학을 통해 배운 열벡터 또는 행벡터가 1차원 행렬이였던 점을 상기해보면
행벡터처럼 (1,4) 또는 열벡터처럼 (4,1)이 되어야 할 듯 싶지만..
shape 속성을 (1,4) 또는 (4,1)로 강제로 지정해보면 2차원 배열이 됩니다.

import numpy as np


A = np.array([1, 2, 3, 4])
print("A  = ", A)
print("A.ndim = ", A.ndim)
print("A.shape = ", A.shape)
print("\n")
# A  = [1 2 3 4]
# A.ndim =  1
# A.shape =  (4,)

# 행벡터처럼 1차원 배열의 shape 속성을 바꾸면
A.shape = 1,4
print("A  = ", A)
print("A.ndim = ", A.ndim)
print("A.shape = ", A.shape)
print("\n")
# A  = [[1 2 3 4]]  괄호가 추가되어 2차원 배열이 되었습니다.
# A.ndim =  2 ndim 속성에서도 차원 개수가 두 개로 증가한 것을 볼 수 있습니다.
# A.shape =  (1, 4) NumPy에선 첫번째 차원의 크기가 1, 두번째 차원의 크기가 4인 2차원 배열입니다.


B = np.array([1, 2, 3, 4])
print("B  = ", B)
print("B.ndim = ", B.ndim)
print("B.shape = ", B.shape)
print("\n")
# B  = [1 2 3 4]
# B.ndim =  1
# B.shape =  (4,)


# 열벡터처럼 1차원 배열의 shape 속성을 바꾸면
B.shape = 4,1
print("B  = \n", B)
print("B.ndim = ", B.ndim)
print("B.shape = ", B.shape)
print("\n")
# B  =    괄호가 추가되어 2차원 배열이 되었습니다.
#  [[1]       열벡터의 경우에는 1차원 배열의 원소들이 개별 1차원 배열로 바뀌고 줄단위로 구분되어 출력됩니다.
#  [2]
#  [3]
#  [4]]
# B.ndim =  2 ndim 속성에서도 차원 개수가 두 개로 증가한 것을 볼 수 있습니다.
# B.shape =  (4, 1) NumPy에선 첫번째 차원의 크기가 4, 두번째 차원의 크기가 1인 2차원 배열입니다.

1.6. NumPy 배열의 원소 접근 방법

NumPy 배열은 차원 개수와 동일한 개수의 인덱스를 사용하여 하나의 원소를 접근할 수 있습니다.
배열의 차원 개수가 증가함에 따라 [ 첫번째 차원 인덱스, 두번째 차원 인덱스, 세번째 차원 인덱스,  .. ] 순으로 인덱스를 적어주면 됩니다.
각 인덱스의 최대값은 차원 크기입니다.

간단한 1차원 NumPy 배열을 예로 들어보겠습니다.

[ 1 2 3 4 ]

이 배열의 shape 속성값은 (4, ) 입니다.  
1 개의 차원만 존재하기 때문에 인덱스 하나로 배열의 원소에 접근할 수 있습니다.
또한 차원의 크기는 4이기 때문에 인덱스 범위는 0 ~ 3입니다.

NumPy 배열의 원소를 출력한 예제 코드를 통해 확인해보겠습니다.

import numpy as np


A = np.array([1, 2, 3, 4])
print("A = ", A)
print("A.ndim = ", A.ndim)
print("A.shape = ", A.shape)
print("\n")
# A =  [1 2 3 4]
# A.ndim =  1
# A.shape =  (4,)


for i in range(A.shape[0]): # 첫번째 차원 크기(A.shape[0])만큼 첫번째 인덱스 사용
   print("A[%d] = %d \t" % (i, A[i]), end="")
print("\n")
# 1차원 배열은 하나의 인덱스로 원소 접근이 가능합니다.
# 배열이름[첫번째 차원의 인덱스]
# A[0] = 1 A[1] = 2 A[2] = 3 A[3] = 4



B = np.array([ [1, 2, 3, 4], [4, 5, 6, 7], [8, 9, 10, 11] ] )
print("B = \n", B)
print("B.ndim = ", B.ndim)
print("B.shape = ", B.shape)
print("\n")
# B =
#  [[ 1  2 3 4]
#  [ 4  5 6 7]
#  [ 8  9 10 11]]
# B.ndim = 2
# B.shape =  (3, 4)


for i1 in range(B.shape[0]): # 첫번째 차원 크기(B.shape[0])만큼 첫번째 인덱스 사용
   for i2 in range(B.shape[1]): # 두번째 차원 크기(B.shape[1])만큼 두번째 인덱스 사용
       print("B[%d,%d] = %d \t" % (i1, i2, B[i1,i2]), end="" )
   print("\n")
# 2차원 배열은 두 개의 인덱스로 원소 접근이 가능합니다.
# 배열이름[첫번째 차원의 인덱스, 두번째 차원의 인덱스]
# B[0,0] = 1 B[0,1] = 2 B[0,2] = 3 B[0,3] = 4
#
# B[1,0] = 4 B[1,1] = 5 B[1,2] = 6 B[1,3] = 7
#
# B[2,0] = 8 B[2,1] = 9 B[2,2] = 10 B[2,3] = 11


C = np.array([ [[1, 2, 3, 4], [4, 5, 6, 7], [8, 9, 10, 11]], [[12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]]  ])
print("C = \n", C)
print("C.ndim = ", C.ndim)
print("C.shape = ", C.shape)
print("\n")
# C =
#  [[[ 1  2 3 4]
#   [ 4 5  6 7]
#   [ 8 9 10 11]]
#
#  [[12 13 14 15]
#   [16 17 18 19]
#   [20 21 22 23]]]
# C.ndim =  3
# C.shape =  (2, 3, 4)


print("----------------------------------------------------------------------------\n")
for i1 in range(C.shape[0]): # 첫번째 차원 크기(C.shape[0])만큼 첫번째 인덱스 사용
   for i2 in range(C.shape[1]): # 두번째 차원 크기(C.shape[1])만큼 두번째 인덱스 사용
       for i3 in range(C.shape[2]): # 세번째 차원 크기(C.shape[2])만큼 세번째 인덱스 사용
           print("C[%2d,%2d,%2d] = %2d \t" % (i1, i2, i3, C[i1,i2,i3]), end="" )
       print("\n")
   print("----------------------------------------------------------------------------\n")
# 3차원 배열은 세개의 인덱스로 원소 접근이 가능합니다.
# 배열이름[첫번째 차원 인덱스, 두번째 차원 인덱스, 세번째 차원 인덱스]
# ----------------------------------------------------------------------------
#
# C[ 0, 0, 0] =  1 C[ 0, 0, 1] =  2 C[ 0, 0, 2] =  3 C[ 0, 0, 3] =  4
#
# C[ 0, 1, 0] =  4 C[ 0, 1, 1] =  5 C[ 0, 1, 2] =  6 C[ 0, 1, 3] =  7
#
# C[ 0, 2, 0] =  8 C[ 0, 2, 1] =  9 C[ 0, 2, 2] = 10 C[ 0, 2, 3] = 11
#
# ----------------------------------------------------------------------------
#
# C[ 1, 0, 0] = 12 C[ 1, 0, 1] = 13 C[ 1, 0, 2] = 14 C[ 1, 0, 3] = 15
#
# C[ 1, 1, 0] = 16 C[ 1, 1, 1] = 17 C[ 1, 1, 2] = 18 C[ 1, 1, 3] = 19
#
# C[ 1, 2, 0] = 20 C[ 1, 2, 1] = 21 C[ 1, 2, 2] = 22 C[ 1, 2, 3] = 23
#
# ----------------------------------------------------------------------------

1.7. print 함수로 NumPy 배열 출력시 시각화 방법

1.4에서 간단히 살펴보았던 print 함수로 NumPy 배열 출력시 어떻게 시각화 하는지 좀 더 살펴보도록 하겠습니다.

print 함수를 사용하여 NumPy 배열 출력한 것을 기준으로 1차원 NumPy 배열을 시각화해보면 아래 그림과 같습니다.
첫번째 차원 축(axis 0)의 방향(화면상 오른쪽)으로 갈수록 첫번째 차원 인덱스 값이 증가하며 최대값은 shape 속성의 첫번째 차원 크기 미만입니다.

A = np.array([1, 2, 3, 4])
print("A = ", A)
# A =  [1 2 3 4]


print 함수를 사용하여 출력한 것을 기준으로 2차원 NumPy 배열을 시각화해보면 아래 그림과 같습니다.

첫번째 차원 축(axis 0)의 방향(화면상 아래쪽)으로 갈수록 첫번째 차원 인덱스 값이 증가하며( B[0, x], B[1, x], B[2, x] ) 최대값은 shape 속성의 첫번째 차원 크기 ( 3, x ) 미만입니다.

두번째 차원 축(axis 1)의 방향(화면상 오른쪽)으로 갈수록 두번째 차원 인덱스 값이 증가하며( B[x, 0], B[x, 1], B[x, 2], B[x, 3]  ) 최대값은 shape 속성의 두번째 차원 크기  ( x, 4 ) 미만입니다.

B = np.array([ [1, 2, 3, 4], [4, 5, 6, 7], [8, 9, 10, 11] ] )
print("B = \n", B)
# B =
#  [[ 1  2 3 4]
#  [ 4  5 6 7]
#  [ 8  9 10 11]]


3차원 이상의 NumPy 배열부터는 print 함수를 사용하여 출력한 결과를 보고 원소의 위치를 파악하기가 쉽지 않습니다.
평면에 3차원 이상의 축을 표현하기 힘들기 때문입니다.

그래서 3차원 NumPy 배열의 경우에는 첫번째 차원 축 방향으로의 증가를 나타내기 위해 2차원 배열을 세로로 출력하고 그 사이에 빈줄을 추가했습니다.
그 다음 두번째 차원 축 방향은 아래 방향이 되며 세번째 차원의 축 방향은  오른쪽이 됩니다.

첫번째 차원 축(axis 0)의 방향(빈줄로 구분)으로 갈수록 첫번째 차원 인덱스 값이 증가하며( C[0, x, x], C[1, x, x] ) 최대값은 shape 속성의 첫번째 차원 크기 ( 2, x, x ) 미만입니다.

두번째 차원 축(axis 1)의 방향(화면상 아래쪽)으로 갈수록 두번째 차원 인덱스 값이 증가하며( C[x, 0, x], C[x, 1, x], C[x, 2, x] ) 최대값은 shape 속성의 두번째 차원 크기 ( x, 3, x ) 미만입니다.

세번째 차원 축(axis 2)의 방향(화면상 오른쪽)으로 갈수록 세번째 차원 인덱스 값이 증가하며( C[x, x, 0], C[x, x, 1], C[x, x, 2], C[x, x, 3] ) 최대값은 shape 속성의 세번째 차원 크기 ( x, x, 4 ) 미만입니다.

C = np.array([ [[1, 2, 3, 4], [4, 5, 6, 7], [8, 9, 10, 11]], [[12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]]  ])
print("C = \n", C)
# C =
#  [[[ 1  2 3 4]
#   [ 4 5  6 7]
#   [ 8 9 10 11]]
#
#  [[12 13 14 15]
#   [16 17 18 19]
#   [20 21 22 23]]]


1.8. NumPy 배열 데이터 타입

NumPy 배열 생성시 데이터를 보고 적절한 타입을 알아서 지정해주지만 따로 지정해 줄 수 도 있습니다.

import numpy as np

A = np.array([1, 2, 3]) # 정수 데이터인 경우
print("A = ", A)
print("A.dtype = ", A.dtype) # ndarray.dtype 속성으로 배열 원소의 데이터 타입 확인
print("\n")
# A =  [1 2 3]
# 정수의 경우 배열의 데이터 타입이 32비트 정수가 되었지만
# 입력한 데이터 또는 코드를 실행한 컴퓨터에 따라 결과가 다를 수 도 있습니다.
# A.dtype =  int32       



B = np.array([0.01, 0.02, 0.03]) # 실수 데이터인 경우
print("B = ", B)
print("B.dtype = ", B.dtype)
print("\n")
# B =  [0.01 0.02 0.03]
# 실수의 경우 배열의 데이터 타입이 64비트 실수가 되었지만
# 입력한 데이터 또는 코드를 실행한 컴퓨터에 따라 결과가 다를 수 도 있습니다.
# B.dtype =  float64     



C = np.array([0.01, 20, 0.03])
print("C = ", C)
print("C.dtype = ", C.dtype)
print("\n")
# C =  [1.e-02 2.e+01 3.e-02]   
# 정수와 실수 값이 섞여 있는 배열의 경우 데이터 타입은 실수가 되며
# 부동소수점(floating-point) 방식으로 출력됩니다.
# 순서대로 1 × 10-2 , 2 × 10,  3 × 10-2을 의미합니다.
# C.dtype =  float64  



# 배열을 생성시 dtype 파라미터에 데이터 타입을 지정해줄 수도 있습니다.
# 정수 데이터를 배열의 원소로 하고 데이터 타입은 실수 타입(numpy.float64)로 지정합니다.
D = np.array([1, 2, 3], dtype=np.float64)
print("D = ", D)
print("D.dtype = ", D.dtype)
# 정수 데이터를 원소로 하는 배열 선언시 실수 데이터 타입을 지정해주면  
# 정수 끝에 소수점(.)이 붙습니다.
# D =  [1. 2. 3.]                 
# D.dtype =  float64

ndarray의 astype 메소드를 사용하여 NumPy 배열의 데이터 타입을 변경할 수 있습니다.

import numpy as np

# 실수를 원소로 하는 배열을 생성하고
A = np.array([1.1, 2.2, 3.3, 4.9])
print("A = ", A)
print("A.dtype = ", A.dtype)
print("\n")
# A =  [1.1 2.2 3.3 4.9]     
# A.dtype =  float64



# 데이터 타입을 정수로 변경해 봅니다.
B = A.astype(np.int32)  
print("B = ", B)
print("B.dtype = ", B.dtype)
print("\n")
# 실수 데이터 타입의 배열을 정수 데이터 타입으로 변경하면 소수점 이하가 버려집니다.
# B =  [1 2 3 4]          
# B.dtype =  int32



# 정수를 원소로 하는 배열을 생성하고
C = np.array([1, 2, 3, 4])    
print("C = ", C)
print("C.dtype = ", C.dtype)
print("\n")
# C =  [1 2 3 4]
# C.dtype =  int32



# 데이터 타입을 실수로 변경해 봅니다.
D = C.astype(np.float64)  
print("D = ", D)
print("D.dtype = ", D.dtype)
# 정수 데이터 타입의 배열을 실수 데이터 타입으로 변경하면 소수점이 표시됩니다.
D =  [1. 2. 3. 4.]   
D.dtype =  float64

인덱스를 사용하여 배열로부터 꺼낸 원소는 NumPy 객체로 NumPy에 내장된 배열 스칼라 타입입니다.

import numpy as np


A = np.array([1, 2, 3])

print("A = ", A)
print("type(A) = ", type(A))  
print("A.dtype = ", A.dtype)
print("\n")
# A =  [1 2 3]

# type 함수는 객체의 타입을 리턴합니다.  NumPy 배열은 numpy.ndarray 객체 입니다.
# type(A) =  <class 'numpy.ndarray'>       

# dtype은 배열 원소의 데이터 타입입니다. 메모리 상에서 원소 하나에 대응하는 블록을 접근하는 방법입니다.
# 예를 들어 int32는 하나의 블록(=하나의 원소)이 4바이트입니다.  
# A.dtype =  int32



print("A[0] = ", A[0])
print("type(A[0]) = ", type(A[0]))
print("A[0].dtype = ", A[0].dtype)
print("isinstance(A[0], np.generic) = ", isinstance(A[0], np.generic))
print("\n")
# A[0] =  1

# 배열의 원소값을 출력하면 정수같지만 NumPy에 내장된 배열 스칼라 타입 객체입니다.         
# type(A[0]) = <class 'numpy.int32'>    

# 원소 하나의 데이터 타입은 자신이 속한 배열과 동일합니다.  
# A[0].dtype = int32     

# 배열의 원소는 배열 스칼라 객체이기 때문에 True가 출력됩니다.  
# isinstance(A[0], np.generic) :  True

# 변수에 배열 스칼라 객체로 1을 저장한 경우입니다.
a = np.int32(1)
print("type(a) = ", type(a))
print("a.dtype = ", a.dtype )
print("isinstance(a, np.generic) = ", isinstance(a, np.generic))
print("\n")
# NumPy에 내장된 배열 스칼라 타입 객체입니다.
# type(a) =  <class 'numpy.int32'>    
# a.dtype =  int32

# 배열 스칼라 객체이기 때문에 True가 출력됩니다.
# isinstance(a, np.generic) :  True



# 변수에 정수를 저장한 경우입니다.
b = 1
print("type(b) = ", type(b))
# 파이썬의 int 타입 객체입니다.
# type(b) =  <class 'int'>                   




다음 사이트를 참고하여 작성되었습니다.

1. NumPy Quickstart tutorial

2. NumPy Reference

3. Scipy Lecture Notes

댓글

이 블로그의 인기 게시물

About AActor!!! "UObject" has no member "BeginPlay"

UNREAL Android build information

C++ 생성자 위임 (delegating constructor)