상세 컨텐츠

본문 제목

NUMPY 기초 문법 정리1_배열을 생성하는 법

PYTHON/NUMPY

by mk coding 2024. 1. 19. 15:08

본문

리스트 대신 NUMPY를 사용하는 이유

많은 숫자 데이터를 하나의 변수에 넣고 관리할 때 리스트는 속도가 느리고 메모리를 많이 차지하는 단점이 있다. 배열을 사용하면 적은 메모리로 많은 데이터를 빠르게 처리할 수 있으며, 파이썬 리스트 객체를 개선한 넘파이의 ndarray 객체를 사용하면 더 많은 데이터를 더 빠르게 처리할 수 있다. 

 

NUMPY

파이썬은 자체적으로 배열 자료형을 제공하지 않기 때문에 배열을 구현한 패키지를 import 해야 한다. 파이썬에서 배열을 사용하기 위한 표준 패키지는 numpy이다. numpy는 c언어로 구현된 파이썬 라이브러리로써, 고성능의 수치 계산을 위해 제작되었다. 

넘파이의 배열 연산은 c로 구현된 내부 반복문을 사용하기 때문에 파이썬 반복문보다 속도가 빠르며 벡터화 연산을 이용하여 간단한 코드로도 복잡한 선형 대수 연산을 수행할 수 있다. 

 

NUMPY 특징

1. 고성능 과학 계산용 패키지로 강력한 N차원 배열 객체 

2. 정교한 브로드캐스팅 (Broadcast) 기능

3. 파이썬 자료형 리스트와 비슷하지만, 더 빠르고 메모리를 효율적으로 관리

4. 반복문 없이 데이터 배열에 대한 처리를 지원하여 빠르고 편리

5. 데이터 과학 도구에 대한 생태계의 핵심을 이루고 있다. 

6. 유용한 선형 대수학, 푸리에 변환 및 난수 기능

7. 범용적 데이터 처리에 사용 가능한 다차원 컨테이너 

리스트로 배열 만드는 방법

a1 = np.array([1,2,3,4,5])
a2 = np.array([[1,2,3],
               [4,5,6],
               [7,8,9]])
a3 = np.array([[[1,2,3],
               [4,5,6],
               [7,8,9]],
              [[10,11,12],
               [13,14,15],
               [16,17,18]],
              [[19,20,21],
               [22,23,24],
               [25,26,27]]])

print("a1: ", a1)
print("a2: ", a2)
print("a3: ", a3)

print("a1 type: ", type(a1))
print("a2 type: ", type(a2))
print("a3 type: ", type(a3))

print("a1 shape: ", a1.shape)
print("a2 shape: ", a2.shape)
print("a3 shape: ", a3.shape)

 

 

3차원 배열의 각 차원 (ex) (4, 4, 3) )

  • 첫 번째 차원(4): 4x3 그리드의 수 (즉, 4개의 2차원 배열이 존재)
  • 두 번째 차원(4): 각 2차원 배열의 행(row) 수
  • 세 번째 차원(3): 각 2차원 배열의 열(column) 수

 

결과

더보기
a1:  [1 2 3 4 5]
a2:  [[1 2 3]
 [4 5 6]
 [7 8 9]]
a3:  [[[ 1  2  3]
  [ 4  5  6]
  [ 7  8  9]]

 [[10 11 12]
  [13 14 15]
  [16 17 18]]

 [[19 20 21]
  [22 23 24]
  [25 26 27]]]
a1 type:  <class 'numpy.ndarray'>
a2 type:  <class 'numpy.ndarray'>
a3 type:  <class 'numpy.ndarray'>
a1 shape:  (5,)
a2 shape:  (3, 3)
a3 shape:  (3, 3, 3)

 

 

배열 생성 및 초기화 

  • np.zeros() : 모든 요소를 0으로 초기화
  • np.ones() : 모든 요소를 1로 초기화
  • np.full() : 모든 요소를 지정한 값으로 초기화
  • np.eye() : 단위행렬(identity matrix) 생성
    • 주대각선의 원소가 모두 1이고 나머지 원소는 모두 0인 정사각 행렬
  • np.tri() : 삼각행렬 생성
  • np.empty() : 초기화되지 않은 배열 생성
    • 초기화가 없어서 배열 생성비용 저렴하고 빠름
    • 초기화되지 않아서 기존 메모리 위치에 존재하는 값이 있음
  • _like() : 지정된 배열과 shape가 같은 행렬 생성
    • np.zeros_like()
    • np.ones_like()
    • np.full_like()
    • np.empty_like()

코드

b1 = np.zeros(10)
b2 = np.zeros((3, 3))
b3 = np.zeros((3, 3, 3))
print("1차원 zero: \n", b1)
print("\n2차원 zero: \n", b2)
print("\n3차원 zero: \n", b3)

b4 = np.ones(10)
b5 = np.ones((3,3))
b6 = np.ones((2,3,5))
print("\n1차원 ones: \n", b4)
print("\n2차원 ones: \n", b5)
print("\n3차원 ones: \n", b6)

b7 = np.full(5, 1.23)
b8 = np.full((3,3), 1.21)
b9 = np.full((3,3,3), 1)
print("\n1차원 full: \n", b7)
print("\n2차원 full: \n", b8)
print("\n3차원 full: \n", b9)

b10 = np.eye(3, k = 0)
b11 = np.eye(3, k = 1)
b12 = np.eye(3, k = -1)
print("\nk=0 eye: \n", b10)
print("\nk=1 eye: \n", b11)
print("\nk=-1 eye: \n", b12)

b13 = np.tri(3, k = 0)
b14 = np.tri(3, k = 1)
b15 = np.tri(3, k = -1)
print("\nk=0 tri: \n", b13)
print("\nk=1 tri: \n", b14)
print("\nk=-1 tri: \n", b15)

b16 = np.empty(3)
b17 = np.empty((3, 3))
b18 = np.empty((3, 3, 3))
print("\n1차원 empty: \n", b16)
print("\n2차원 empty: \n", b17)
print("\n3차원 empty: \n", b18)

print("a2 : ", a2) 
b19 = np.zeros_like(a2)
b20 = np.ones_like(a2)
b21 = np.full_like(a2, 3)
print("\na2 zeros_like: \n", b19)
print("\na2 ones_like: \n", b20)
print("\na2 full_like: \n", b21)

 

결과

더보기
1차원 zero: 
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]

2차원 zero: 
 [[0. 0. 0.]
 [0. 0. 0.]
 [0. 0. 0.]]

3차원 zero: 
 [[[0. 0. 0.]
  [0. 0. 0.]
  [0. 0. 0.]]

 [[0. 0. 0.]
  [0. 0. 0.]
  [0. 0. 0.]]

 [[0. 0. 0.]
  [0. 0. 0.]
  [0. 0. 0.]]]

1차원 ones: 
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]

2차원 ones: 
 [[1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]]

3차원 ones: 
 [[[1. 1. 1. 1. 1.]
  [1. 1. 1. 1. 1.]
  [1. 1. 1. 1. 1.]]

 [[1. 1. 1. 1. 1.]
  [1. 1. 1. 1. 1.]
  [1. 1. 1. 1. 1.]]]

1차원 full: 
 [1.23 1.23 1.23 1.23 1.23]

2차원 full: 
 [[1.21 1.21 1.21]
 [1.21 1.21 1.21]
 [1.21 1.21 1.21]]

3차원 full: 
 [[[1 1 1]
  [1 1 1]
  [1 1 1]]

 [[1 1 1]
  [1 1 1]
  [1 1 1]]

 [[1 1 1]
  [1 1 1]
  [1 1 1]]]

k=0 eye: 
 [[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]

k=1 eye: 
 [[0. 1. 0.]
 [0. 0. 1.]
 [0. 0. 0.]]

k=-1 eye: 
 [[0. 0. 0.]
 [1. 0. 0.]
 [0. 1. 0.]]

k=0 tri: 
 [[1. 0. 0.]
 [1. 1. 0.]
 [1. 1. 1.]]

k=1 tri: 
 [[1. 1. 0.]
 [1. 1. 1.]
 [1. 1. 1.]]

k=-1 tri: 
 [[0. 0. 0.]
 [1. 0. 0.]
 [1. 1. 0.]]
 
 1차원 empty: 
 [1. 1. 1.]

2차원 empty: 
 [[0. 0. 0.]
 [1. 0. 0.]
 [1. 1. 0.]]

3차원 empty: 
 [[[0. 0. 0.]
  [0. 0. 0.]
  [0. 0. 0.]]

 [[0. 0. 0.]
  [0. 0. 0.]
  [0. 0. 0.]]

 [[0. 0. 0.]
  [0. 0. 0.]
  [0. 0. 0.]]]
a2 :  [[1 2 3]
 [4 5 6]
 [7 8 9]]

a2 zeros_like: 
 [[0 0 0]
 [0 0 0]
 [0 0 0]]

a2 ones_like: 
 [[1 1 1]
 [1 1 1]
 [1 1 1]]

a2 full_like: 
 [[3 3 3]
 [3 3 3]
 [3 3 3]]

생성한 값으로 배열 생성 

  • arange() : 정수 범위로 배열 생성. 파이썬의 range()와 유사. start부터 stop미만까지 step 간격으로 데이터를 생성한 후 배열을 생성. 요소의 개수가 아닌 데이터의 간격을 기준으로 배열 생성 
    • np.array(start, stop, step, dtype = None)
  • linspace() : 범위 내에서 균등 간격의 배열 생성. start부터 stop의 범위에서 num개를 균일한 간격으로 데이터를 생성하고 배열을 만드는 함수. 요소 개수를 기준으로 균등 간격의 배열을 생성 
    • np.linspace(start, stop, num = 50, endpoint = True, retstep = False, dtype = None)
  • logspace() : 범위 내에서 균등 간격으로 로그 스케일로 배열 생성. 로그 스케일의 linsapace 함수. 로스 스케일로 지정된 범위에서 num 개수만큼 균등 간격으로 데이터 생성한 후 배열 생성 
    • np.logspace(start, stop, num = 50, endpoint = True, base = 10.0, dtype = None)
c1 = np.arange(0, 50, 3)
c2 = np.linspace(0, 1, 5)
c3 = np.logspace(0.1, 1, 20)

print("\n설정한 범위 안에 지정한 간격\n", c1)
print("\n설정한 범위 안에 등간격\n", c2)
print("\n설정한 범위 안에 로그 간격\n", c3)
더보기
설정한 범위 안에 지정한 간격
 [ 0  3  6  9 12 15 18 21 24 27 30 33 36 39 42 45 48]

설정한 범위 안에 등간격
 [0.   0.25 0.5  0.75 1.  ]

설정한 범위 안에 로그 간격
 [ 1.25892541  1.40400425  1.565802    1.74624535  1.94748304  2.1719114
  2.42220294  2.70133812  3.0126409   3.35981829  3.74700446  4.17881006
  4.66037703  5.19743987  5.79639395  6.46437163  7.2093272   8.04013161
  8.9666781  10.        ]

랜덤값으로 배열 생성 요약

  • seed: 난수 발생을 위한 시드(seed) 지정 -> 코드 돌릴 때마다 동일한 난수 생성 가능 
  • permutation: 순서를 임의로 바꾸거나 임의의 순열 반환
  • shuffle: 리스트나 배열의 순서를 뒤섞음
  • random: 랜덤한 수의 배열 생성
  • rand: 균등분포에서 표본 추출
  • randint: 주어진 최소/최대 범위의 난수 추출
  • randn: 표준편차가 1, 평균값 0인 정규분포의 표본 추출
  • binomial: 이항분포에서 표본 추출
  • normal: 정규분포(가우시안)에서 표본 추출
  • beta: 베타분포에서 표본 추출
  • chisquare: 카이제곱분포에서 표본 추출
  • gamma: 감마분포에서 표본 추출
  • uniform: 균등(0, 1)분포에서 표본 추출

np.random.random과 np.random.rand의 차이

  1. np.random.random(size=None): 이 함수는 입력된 size에 따라 무작위 실수를 생성합니다. size를 지정하지 않으면 하나의 실수를 생성하고, 튜플 형태로 size를 지정하면 해당 형태의 배열을 생성합니다. 예를 들어, np.random.random((3, 3))은 3x3 배열을 생성합니다.
  2. np.random.rand(d0, d1, ..., dn): 이 함수는 입력된 차원에 따라 무작위 실수를 생성합니다. 차원을 지정하지 않으면 하나의 실수를 생성하고, 차원을 하나 이상 지정하면 해당 차원의 배열을 생성합니다. 예를 들어, np.random.rand(3, 3)은 3x3 배열을 생성합니다.

따라서 이 두 함수의 주요 차이점은 입력 방식입니다. np.random.random은 size에 튜플 형태로 배열의 형태를 지정하고, np.random.rand는 각 차원의 크기를 직접 인자로 전달합니다. 결과적으로 두 함수는 동일한 분포(0에서 1 사이의 균일 분포)의 무작위 수를 생성하지만, 배열의 형태를 지정하는 방식이 다릅니다.

 

코드

d1 = np.random.random(3)
d2 = np.random.random((3,3))
d3 = np.random.random((3,3,3))
print("\n1차원 배열에서 [0,1)사이 랜덤값\n", d1)
print("\n2차원 배열에서 [0,1)사이 랜덤값\n", d2)
print("\n3차원 배열에서 [0,1)사이 랜덤값\n", d3)

d4 = np.random.randint(0, 10, 3)
d5 = np.random.randint(0, 10, (3,3))
d6 = np.random.randint(0, 10, (3,3,3))
print("\n1차원 배열에서 설정 범위 정수형 랜덤값\n", d4)
print("\n2차원 배열에서 설정 범위 정수형 랜덤값\n", d5)
print("\n3차원 배열에서 설정 범위 정수형 랜덤값\n", d6)

d7 = np.random.normal(0, 3, size = 3)
d8 = np.random.normal(1, 5, (3,3))
d9 = np.random.normal(2, 7, size = (3,3,3))
print("\n평균이 0이고 표준편차가 3인 1차원 3개 랜덤값\n", d7)
print("\n평균이 1이고 표준편차가 5인 2차원 배열 랜덤값\n", d8)
print("\n평균이 2이고 표준편차가 7인 3차원 배열 랜덤값\n", d9)

d10 = np.random.rand(3)
d11 = np.random.rand(3, 3)
d12 = np.random.rand(3, 3, 3)
print("\n1차원 배열에서 0과 1 사이의 균일 분포를 따르는 난수를 생성\n", d10)
print("\n2차원 배열에서 0과 1 사이의 균일 분포를 따르는 난수를 생성\n", d11)
print("\n3차원 배열에서 0과 1 사이의 균일 분포를 따르는 난수를 생성\n", d12)

d13 = np.random.randn(3)
d14 = np.random.randn(3, 3)
d15 = np.random.randn(3, 3, 3)
print("\n1차원 배열에서 표준정규분포를 따르는 난수를 생성\n", d13)
print("\n2차원 배열에서 표준정규분포를 따르는 난수를 생성\n", d14)
print("\n3차원 배열에서 표준정규분포를 따르는 난수를 생성\n", d15)

 

결과

더보기
1차원 배열에서 [0,1)사이 랜덤값
 [0.86946585 0.88952207 0.75526839]

2차원 배열에서 [0,1)사이 랜덤값
 [[0.95683867 0.97049848 0.03704888]
 [0.90914317 0.70387794 0.31720288]
 [0.67157498 0.98603087 0.69154972]]

3차원 배열에서 [0,1)사이 랜덤값
 [[[0.70495683 0.80995285 0.23896313]
  [0.8645421  0.62840465 0.67017125]
  [0.83227556 0.38840293 0.25898873]]

 [[0.39682095 0.54931439 0.11903838]
  [0.00715198 0.74944205 0.55897255]
  [0.21737949 0.25788276 0.56419962]]

 [[0.11177761 0.13488424 0.53705247]
  [0.25206901 0.67083177 0.18205277]
  [0.85568437 0.17426277 0.6972453 ]]]

1차원 배열에서 설정 범위 정수형 랜덤값
 [4 8 6]

2차원 배열에서 설정 범위 정수형 랜덤값
 [[6 7 3]
 [7 3 5]
 [3 0 3]]

3차원 배열에서 설정 범위 정수형 랜덤값
 [[[7 5 5]
  [0 8 8]
  [3 4 5]]

 [[9 6 8]
  [4 9 9]
  [5 4 4]]

 [[3 9 9]
  [9 0 4]
  [8 4 9]]]

평균이 0이고 표준편차가 3인 1차원 3개 랜덤값
 [-4.75490316 -0.18783676  4.15956691]

평균이 1이고 표준편차가 5인 2차원 배열 랜덤값
 [[ 0.13533808 -3.23990666  6.05984193]
 [ 5.95856718 -3.37536765  9.73709801]
 [ 3.58651562  1.46904918  9.11710218]]

평균이 2이고 표준편차가 7인 3차원 배열 랜덤값
 [[[ -1.97337334   4.61221964   3.93999001]
  [  1.72416845  -2.05775911   8.22461506]
  [ -5.50725618  -0.45088988   7.66724251]]

 [[ 10.19288365   7.47385768  -4.82156061]
  [  8.87069467   5.55019471  -0.33801297]
  [ 10.23296311   5.75735303  -1.98569397]]

 [[  0.99159038   2.82945247  -7.39960646]
  [-17.62512422  10.38902277   2.43197522]
  [ 10.76598361  -7.55649195   2.01685758]]]

1차원 배열에서 0과 1 사이의 균일 분포를 따르는 난수를 생성
 [0.25958018 0.35421106 0.33842467]

2차원 배열에서 0과 1 사이의 균일 분포를 따르는 난수를 생성
 [[0.59281147 0.53818162 0.92597936]
 [0.8135177  0.93266712 0.56874908]
 [0.34724813 0.18058273 0.19269196]]

3차원 배열에서 0과 1 사이의 균일 분포를 따르는 난수를 생성
 [[[0.93286307 0.09395866 0.62288734]
  [0.39281406 0.38737784 0.8655914 ]
  [0.05309743 0.62015922 0.87627933]]

 [[0.01963411 0.86983375 0.31068603]
  [0.55019072 0.13354848 0.4983024 ]
  [0.71391607 0.93378937 0.87579569]]

 [[0.39170455 0.26283736 0.64286232]
  [0.76684444 0.90118473 0.0012773 ]
  [0.45470239 0.10268806 0.49604526]]]

1차원 배열에서 표준정규분포를 따르는 난수를 생성
 [ 1.52352491 -0.28167244 -1.38022747]

2차원 배열에서 표준정규분포를 따르는 난수를 생성
 [[-0.6078648  -1.77823779 -0.51114142]
 [ 0.02409207  0.84143194  1.02433787]
 [ 0.04672084 -0.59002246 -1.28394965]]

3차원 배열에서 표준정규분포를 따르는 난수를 생성
 [[[-0.37993155  1.65535516 -0.9828355 ]
  [-0.66208863  1.12911477  0.09533752]
  [ 0.66585077 -0.24787554  0.75024623]]

 [[ 1.78488855  1.90083705 -1.50793375]
  [ 0.17540813  1.23031778  1.62831788]
  [ 0.19447913 -0.38919338  0.0599989 ]]

 [[ 0.43938678 -0.53418921 -0.09160102]
  [ 0.46522262 -0.06753373 -0.65213317]
  [-0.94061396  0.63707854 -0.41959983]]]

 

표준 데이터 타입 요약

  • bool_ : 바이트로 저장된 불리언(Boolean)으로 True 또는 False 값을 가짐
  • int_ : 기본 정수(Integer) 타입
  • intc : C 언어에서 사용되는 int 와 동일 (일반적으로 int32 또는 int64 )
  • intp : 인덱싱에 사용되는 정수 (C 언어에서 ssize_t 와 동일; 일반적으로 int32 또는 int64
  • int8 : 바이트(Byte) (-128 ~ 127)
  • int16 : 정수 (-32768 ~ 32767)
  • int32 : 정수 (-2147483648 ~ 2147483647)
  • int64 : 정수(-9223372036854775808 ~ 9223372036854775807)
  • uint8 : 부호 없는 정수 (0 ~ 255)
  • uint16 : 부호 없는 정수 (0 ~ 65535)
  • uint32 : 부호 없는 정수 (0 ~ 4294967295)
  • uint64 : 부호 없는 정수 (0 ~ 18446744073709551615)
  • float16 : 반정밀 부동 소수점(Half precision float): 부호 비트, 5비트 지수, 10비트 가수
  • float32 : 단정밀 부동 소수점(Single precision float): 부호 비트, 8비트 지수, 23비트 가수
  • float64 : 배정밀 부동 소수점(Double precision float): 부호 비트, 11비트 지수, 52비트 가수
  • float_ : float64를 줄여서 표현
  • complex64 : 복소수(Complex number), 두 개의 32비트 부동 소수점으로 표현
  • complex128 : 복소수, 두 개의 64비트 부동 소수점으로 표현
  • complex_ : complex128를 줄여서 표현

코드

e1 = np.zeros(3, dtype = bool)
e2 = np.ones((5, 5), dtype = int)
e3 = np.full((3, 3), 1., dtype = float)
print("\nbooltype zeros\n", e1)
print("\ninttype ones\n", e2)
print("\nfloattype full\n", e3)

 

결과

더보기
booltype zeros
 [False False False]

inttype ones
 [[1 1 1 1 1]
 [1 1 1 1 1]
 [1 1 1 1 1]
 [1 1 1 1 1]
 [1 1 1 1 1]]

floattype full
 [[1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]]

 

날짜/시간 배열 생성

코드 의미 상대적 시간 범위 절대적 시간 범위
Y  ± 9.2e18 년  [9.2e18 BC, 9.2e18 AD]
월  ± 7.6e17 년  [7.6e17 BC, 7.6e17 AD]
주  ± 1.7e17 년  [1.7e17 BC, 1.7e17 AD]
일  ± 2.5e16 년 [2.5e16 BC, 2.5e16 AD]
시  ± 1.0e15 년  [1.0e15 BC, 1.0e15 AD]
분  ± 1.7e13 년  [1.7e13 BC, 1.7e13 AD]
± 2.9e12 년  [ 2.9e9 BC, 2.9e9 AD]
ms  밀리초  ± 2.9e9 년  [ 2.9e6 BC, 2.9e6 AD] 
us  마이크로초  ± 2.9e6 년  [ 290301 BC, 294241 AD]
ns  나노초  ± 292 년  [ 1678 AD, 2262 AD]
ps  피코초  ± 106 일  [ 1969 AD, 1970 AD]
fs  펨토초  ± 2.6 시간  [ 1969 AD, 1970 AD]
as  아토초  ± 9.2 초  [ 1969 AD, 1970 AD]

 

코드

date1 = np.array('2020-01-01', dtype = np.datetime64)
print('\n날짜 배열 생성: \n', date)
print(type(date))

print('\n날짜 range: \n', date+np.arange(12))
date2 = np.datetime64('2020-06-01 12:00')
print('\n날짜 출력\n', date2)
print(type(date2))

date3 = np.datetime64('2020-06-01 12:00:12.34', 'ns')
print('\n초단위 날짜 출력\n', date3)
print(type(date3))

 

결과

더보기
날짜 배열 생성: 
 2020-01-01
<class 'numpy.ndarray'>

날짜 range: 
 ['2020-01-01' '2020-01-02' '2020-01-03' '2020-01-04' '2020-01-05'
 '2020-01-06' '2020-01-07' '2020-01-08' '2020-01-09' '2020-01-10'
 '2020-01-11' '2020-01-12']

날짜 출력
 2020-06-01T12:00
<class 'numpy.datetime64'>

초단위 날짜 출력
 2020-06-01T12:00:12.340000000
<class 'numpy.datetime64'>

 

출처: 이수안 컴퓨터 연구소

 

관련글 더보기