Lesson 05: numpy 공부 1단계 ~ 2단계

Author

최규빈

Published

July 24, 2023

import

import numpy as np

넘파이 공부 1단계

선언

a=np.array([1,2,3]) # list를 만들고 ndarray화 시킴 
l=[1,2,3]

기본연산 브로드캐스팅

a+1 ## [1,2,3] + 1 = [2,3,4]
array([2, 3, 4])
l+1
TypeError: can only concatenate list (not "int") to list
a*2
array([2, 4, 6])
l*2
[1, 2, 3, 1, 2, 3]
a/2
array([0.5, 1. , 1.5])
l/2
TypeError: unsupported operand type(s) for /: 'list' and 'int'
a**2
array([1, 4, 9])
l**2
TypeError: unsupported operand type(s) for ** or pow(): 'list' and 'int'
a%2 # %2 = 2로 나눈 나머지를 리턴 a=[1,2,3] 
array([1, 0, 1])
l%2
TypeError: unsupported operand type(s) for %: 'list' and 'int'

기타수학연산지원

np.sqrt(a), np.sqrt(l)
(array([1.        , 1.41421356, 1.73205081]),
 array([1.        , 1.41421356, 1.73205081]))
np.log(a), np.log(l)
(array([0.        , 0.69314718, 1.09861229]),
 array([0.        , 0.69314718, 1.09861229]))
np.exp(a), np.exp(l)
(array([ 2.71828183,  7.3890561 , 20.08553692]),
 array([ 2.71828183,  7.3890561 , 20.08553692]))
np.sin(a), np.sin(l)
(array([0.84147098, 0.90929743, 0.14112001]),
 array([0.84147098, 0.90929743, 0.14112001]))

넘파이 공부 2단계

인덱싱 1차원

- 선언

l=[11,22,33,44,55,66] 
a=np.array(l) 

- 인덱스로 접근

l[0],l[1],l[2],l[3],l[-2],l[-1]
(11, 22, 33, 44, 55, 66)
a[0],a[1],a[2],a[3],a[-2],a[-1]
(11, 22, 33, 44, 55, 66)

- : 이용 (슬라이싱)

l[2:4] # index 2에서 시작, index 4는 포함하지 않음 
[33, 44]
a[2:4] 
array([33, 44])

- 정수배열에 의한 인덱싱

a
array([11, 22, 33, 44, 55, 66])
a[[0,2,4]] # index=0, index=2, index=4 에 해당하는 원소를 뽑고 싶다 
array([11, 33, 55])
l[[0,2,4]] # 리스트는 불가능 
TypeError: list indices must be integers or slices, not list

- 부울값에 의한 인덱싱

a
array([11, 22, 33, 44, 55, 66])
a[[True,False,True,False,True,False]] 
array([11, 33, 55])

응용하면?

a < 33 
array([ True,  True, False, False, False, False])
a[a<33]
array([11, 22])

리스트는 불가능

l<33 # 여기에서부터 불가능 
TypeError: '<' not supported between instances of 'list' and 'int'
l[[True,False,True,False,True,False]] # 이것도 불가능 
TypeError: list indices must be integers or slices, not list

인덱싱 2차원

- 중첩리스트와 2차원 np.array 선언

A = [[1,2,3,4],[-1,-2,-3,-4],[5,6,7,8],[-5,-6,-7,-8]]
A2 = np.array(A)
A2
array([[ 1,  2,  3,  4],
       [-1, -2, -3, -4],
       [ 5,  6,  7,  8],
       [-5, -6, -7, -8]])
A
[[1, 2, 3, 4], [-1, -2, -3, -4], [5, 6, 7, 8], [-5, -6, -7, -8]]

- A의 원소 인덱싱

A[0][0] # (1,1)의 원소 
1
A[1][2] # (2,3)의 원소 
-3
A[-1][0] # (4,1)의 원소 
-5

- A2의 원소 인덱싱

A2[0][0] # (1,1)의 원소 
1
A2[1][2] # (2,3)의 원소 
-3
A2[-1][0] # (4,1)의 원소 
-5

- A2에서만 되는 기술 (넘파이에서 제시하는 신기술, R에서는 기본적으로 쓰던것, 이중list는 불가능)

A2[0,0] # (1,1)의 원소 
1
A2[1,2] # (2,3)의 원소 
-3
A2[-1,0] # (4,1)의 원소 
-5

- 정수배열에 의한 인덱싱 & 슬라이싱!

A2
array([[ 1,  2,  3,  4],
       [-1, -2, -3, -4],
       [ 5,  6,  7,  8],
       [-5, -6, -7, -8]])
A2[0,0:2] # 1행1열, 1행2열 
array([1, 2])
A2[0,:] # 1행 
array([1, 2, 3, 4])
A2[0] # 1행
array([1, 2, 3, 4])
A2[[0,2],:] # 1행, 3행 
array([[1, 2, 3, 4],
       [5, 6, 7, 8]])
A2[[0,2]] # 1행, 3행 
array([[1, 2, 3, 4],
       [5, 6, 7, 8]])
A2[:,0] # 1열 
array([ 1, -1,  5, -5])
A2[:,[0]] # 1열 
array([[ 1],
       [-1],
       [ 5],
       [-5]])
A2[:,[0,2]] # 1열, 3열
array([[ 1,  3],
       [-1, -3],
       [ 5,  7],
       [-5, -7]])
A2[0:2,[0,2]] # 1행~2행 //  1열,3열 
array([[ 1,  3],
       [-1, -3]])

1차원 배열의 선언

- 리스트나 튜플을 선언하고 형변환

np.array((1,2,3)) # 튜플->넘파이어레이 
array([1, 2, 3])
np.array([1,2,3]) # 리스트 ->넘파이어레이 
array([1, 2, 3])

- range()를 이용해서 선언하고 형변환

np.array(range(10)) # range(10) -> 넘파이어레이 
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

- np.zeros, np.ones

np.zeros(3) 
array([0., 0., 0.])
np.ones(4)
array([1., 1., 1., 1.])

- np.linspace

np.linspace(0,1,12) # 0에서 시작하고 1에서 끝남 (양끝점 모두 포함)
array([0.        , 0.09090909, 0.18181818, 0.27272727, 0.36363636,
       0.45454545, 0.54545455, 0.63636364, 0.72727273, 0.81818182,
       0.90909091, 1.        ])
len(np.linspace(0,1,12)) # 길이는 12
12

- np.arange

np.arange(5) # np.array(range(5))
array([0, 1, 2, 3, 4])
np.arange(1,6) # np.array(range(1,6))
array([1, 2, 3, 4, 5])

reshape

- reshape: ndarray의 특수한 기능

a=np.array([11,22,33,44,55,66])
a ## 길이가 6인 벡터 
array([11, 22, 33, 44, 55, 66])
a.reshape(2,3) ## (2,3) matrix 라고 생각해도 무방 
array([[11, 22, 33],
       [44, 55, 66]])

note: reshape은 a자체를 변화시키는것은 아님

a # a는 그대로 있음 
array([11, 22, 33, 44, 55, 66])
b= a.reshape(2,3) # a를 reshape한 결과를 b에 저장 
b
array([[11, 22, 33],
       [44, 55, 66]])
a # a는 여전히 그대로 있음
array([11, 22, 33, 44, 55, 66])

- 다시 b를 a처럼 바꾸고 싶다

b
array([[11, 22, 33],
       [44, 55, 66]])
b.reshape(6) # b는 (2,3) matrix , 그런데 이것을 길이가 6인 벡터로 만들고 싶다. 
array([11, 22, 33, 44, 55, 66])

- reshape with -1

a=np.arange(24) # np.array(range(24))
a
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19, 20, 21, 22, 23])
a.reshape(2,-1)
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]])
a.reshape(3,-1)
array([[ 0,  1,  2,  3,  4,  5,  6,  7],
       [ 8,  9, 10, 11, 12, 13, 14, 15],
       [16, 17, 18, 19, 20, 21, 22, 23]])
a.reshape(4,-1)
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23]])
a.reshape(5,-1)
ValueError: cannot reshape array of size 24 into shape (5,newaxis)
a.reshape(6,-1)
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15],
       [16, 17, 18, 19],
       [20, 21, 22, 23]])
a.reshape(7,-1)
ValueError: cannot reshape array of size 24 into shape (7,newaxis)
a.reshape(8,-1)
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11],
       [12, 13, 14],
       [15, 16, 17],
       [18, 19, 20],
       [21, 22, 23]])
a.reshape(12,-1)
array([[ 0,  1],
       [ 2,  3],
       [ 4,  5],
       [ 6,  7],
       [ 8,  9],
       [10, 11],
       [12, 13],
       [14, 15],
       [16, 17],
       [18, 19],
       [20, 21],
       [22, 23]])
b= a.reshape(12,-1)
b
array([[ 0,  1],
       [ 2,  3],
       [ 4,  5],
       [ 6,  7],
       [ 8,  9],
       [10, 11],
       [12, 13],
       [14, 15],
       [16, 17],
       [18, 19],
       [20, 21],
       [22, 23]])
b.reshape(-1) # b를 다시 길이가 24인 벡터로!
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19, 20, 21, 22, 23])

2차원 배열의 선언

np.zeros((3,3))
array([[0., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.]])
np.ones((3,3))
array([[1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.]])
np.eye(3)
array([[1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])
np.diag([1,2,3,-1])
array([[ 1,  0,  0,  0],
       [ 0,  2,  0,  0],
       [ 0,  0,  3,  0],
       [ 0,  0,  0, -1]])

랜덤으로 배열 생성

np.random.randn(10) # 표쥰정규분포에서 10개를 뽑음 
array([ 0.27184979, -0.4540305 ,  0.24538219, -3.11389327,  1.06478234,
        0.12051154,  0.01503231, -0.06744028,  2.30710253,  0.78840453])
np.random.rand(10) # 0~1사이에서 10개를 뽑음
array([0.67729671, 0.19584606, 0.4564896 , 0.9308976 , 0.49080792,
       0.03410752, 0.47480477, 0.44519947, 0.20608611, 0.85576604])
np.random.randn(4).reshape(2,2) # 표준정규분포에서 4개를 뽑고 (2,2) ndarray로 형태변환 
array([[-0.97378852,  0.5250826 ],
       [-0.97400213, -0.59600022]])
np.random.rand(4).reshape(2,2) # 0~1 4개를 뽑고 (2,2) ndarray로 형태변환 
array([[0.03708309, 0.56122376],
       [0.80934488, 0.65723348]])

행렬관련기능

A=np.arange(4).reshape(2,2) 
A
array([[0, 1],
       [2, 3]])
A.T # .T는 전치행렬을 구해줌 
array([[0, 2],
       [1, 3]])
np.linalg.inv(A) # np.linalg.inv는 역행렬을 구해주는 함수 
array([[-1.5,  0.5],
       [ 1. ,  0. ]])
A @ np.linalg.inv(A) # @는 행렬곱을 수행 
array([[1., 0.],
       [0., 1.]])

차원

- 넘파이배열의 차원은 .shape 으로 확인가능

- 아래는 모두 미묘하게 다르다.

a=np.array(3.14) # 스칼라, 0d array 
a, a.shape
(array(3.14), ())
a=np.array([3.14]) # 벡터, 1d array 
a, a.shape
(array([3.14]), (1,))
a=np.array([[3.14]]) # 매트릭스, 2d array 
a, a.shape
(array([[3.14]]), (1, 1))
a=np.array([[[3.14]]]) # 텐서, 3d array 
a, a.shape
(array([[[3.14]]]), (1, 1, 1))

Quiz

1. shape이 ()인 numpy array를 만들어라. (즉 차원이 0인 np.array를 만들어라)

2 a의 모든 원소에 1을 더하는 코드를 작성하라. (numpy를 이용할것)

a=[1,3,2,5,-3,3,8,2,3,1] 

3 아래와 같은 수열을 생생성하라.

0,1,2,3,4,5,...,99 

위의 수열에서 1,4,7,10,13,… 번째의 원소를 뽑아서 아래와 같은 수열을 만들어라. (첫번째 원소는 0이다)

0,3,6,9,12,...,93,96,99

4. shape이 (5,5)인 단위행렬을 만들어라.

5. numpy를 이용하여 아래의 역행렬을 구하라.

\[\begin{bmatrix} 1& 0 \\ 0& 3 \end{bmatrix}\]

6. 본인의 생년월일로 랜덤시드를 설정하고 표준정규분포에서 1000개의 난수를 생성하라.

# 생년월일이 21년 07월 06일 이라면 아래와 같이 시드설정 
np.random.seed(20210706)

7. 6의 결과로 나온 1000개의 난수중 1.96보다 크거나 -1.96보다 작은 작은값은 모두 몇개인가?

8. 아래와 같은 배열을 선언하라.

a=np.arange(12).reshape(3,4)
a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

차원의 수를 유지하면서 1열을 추출하는 코드를 작성하라. 즉 결과가 아래와 같이 나오도록 하라.

array([[0],
       [4],
       [8]])

9. 아래의 코드를 관찰하라.

np.random.seed(43052)
a=np.random.randint(low=20,high=25,size=(10,10))

a에서 20,21,22는 각각 몇개씩 있는가?

note 공부를 위하여 np.random.randint()의 기능을 chatGPT등으로 확인해 볼 것

10. 아래의 코드를 관찰하라.

lst = [[i==j for i in range(5)] for j in range(5)]
lst
[[True, False, False, False, False],
 [False, True, False, False, False],
 [False, False, True, False, False],
 [False, False, False, True, False],
 [False, False, False, False, True]]

lst를 이용하여 shape이 (5,5)인 단위행렬을 만들어라.

# 출력결과는 아래와 같이 나와야 한다. 
array([[1, 0, 0, 0, 0],
       [0, 1, 0, 0, 0],
       [0, 0, 1, 0, 0],
       [0, 0, 0, 1, 0],
       [0, 0, 0, 0, 1]])

12. 적당한 코드를 이용하여 아래와 같은 리스트를 생성하라.

lst
[[0, 1, 2, 3, 4],
 [1, 2, 3, 4, 5],
 [2, 3, 4, 5, 6],
 [3, 4, 5, 6, 7],
 [4, 5, 6, 7, 8]]

이를 이용하여 아래와 같은 행렬을 선언하라.

arr 
array([[0, 1, 2, 3, 4],
       [1, 2, 3, 4, 5],
       [2, 3, 4, 5, 6],
       [3, 4, 5, 6, 7],
       [4, 5, 6, 7, 8]])

13. 적당한 코드를 이용하여 아래와 같은 행렬을 선언하라.

# 출력결과는 아래와 같아야 한다.
array([[1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
       [1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
       [0, 1, 1, 1, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
       [0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
       [0, 0, 0, 0, 1, 1, 1, 0, 0, 0],
       [0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
       [0, 0, 0, 0, 0, 0, 1, 1, 1, 0],
       [0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
       [0, 0, 0, 0, 0, 0, 0, 0, 1, 1]])

14. 성공확률이 45%인 시행을 100번 반복하여 성공하면 True, 실패하면 False를 기록하는 난수열을 생성하라.

hint:

np.random.rand() # 0~1사이의 값이 임의로 생성
0.1721011158345127
np.random.rand() < 0.45 # 0~1사이에 랜덤으로 생성된 값이 0.45보다 작다면 True를 리턴 
False