15 분 소요

인덱싱과 슬라이싱을 이용한 배열의 원소 조회 및 변경

배열 인덱싱(Indexing)

  • index
    • 배열내의 원소의 식별번호
    • 0부터 시작
  • indexing – index를 이용해 원소 조회
    • [] 표기법 사용
  • 구문
    • ndarray[index]
    • 양수는 지정한 index의 값을 조회한다.
    • 음수는 뒤부터 조회한다.
      • 마지막 index가 -1
    • 2차원배열의 경우
      • arr[0축 index, 1축 index]
      • 파이썬 리스트와 차이점
    • N차원 배열의 경우
      • arr[0축 index, 1축 index, …, n축 index]
    • 팬시(fancy) 인덱싱
    • 여러개의 원소를 한번에 조회할 경우 리스트에 담아 전달한다.
    • 다차원 배열의 경우 각 축별로 list로 지정
    • arr[[1,2,3,4,5]]
      • 1차원 배열(vector): 1,2,3,4,5 번 index의 원소들 한번에 조회
    • arr[[0,3], [1,4]]
      • [0,3] - 1번축 index list, [1,4] - 2번축 index list
      • 2차원 배열(matrix): [0,1], [3,4] 의 원소들 조회
import numpy as np
a = np.arange(30)
a.shape
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, 24, 25, 26, 27, 28, 29])

**1. 조회.**

a[1]
1

**2. 여러 index들의 값 조회 -> fancy indexing => index들을 리스트로 묶어서 전달.**

a[[1,3,2,7]]
array([1, 3, 2, 7])

**3. 변경.**

a[1] = 1000
a
array([   0, 1000,    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,   28,   29])

**4. 일괄변경**

a[[2, 4, 5]] = 5000
a
array([   0, 1000, 5000,    3, 5000, 5000,    6,    7,    8,    9,   10,
         11,   12,   13,   14,   15,   16,   17,   18,   19,   20,   21,
         22,   23,   24,   25,   26,   27,   28,   29])
a[[8, 9, 10]] = 8000, 9000, 10000
a
array([    0,  1000,  5000,     3,  5000,  5000,     6,     7,  8000,
        9000, 10000,    11,    12,    13,    14,    15,    16,    17,
          18,    19,    20,    21,    22,    23,    24,    25,    26,
          27,    28,    29])

**5. ( 30 , ) 1차원배열을 ( 5 , 6 ) 2차원배열로 reshape.**

  • size만 동일하면 reshape 가능!!!!
a2 = np.arange(30).reshape(5, 6)
a2
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],
       [24, 25, 26, 27, 28, 29]])
a2[0] # 0축의 index 0을 조회
a2[0,3] # a[axis0, axis1]
a2[-1,-1]
29

**6. Fancy indexing 으로 조회.**

a2[0, 2]
a2[3, 4]
22
a2[[0,3], [2,4]]
array([ 2, 22])
  • **[ 0 , 2 ] 와 [ 3 , 4 ]를 조회한 것이다.**
a3 = np.arange(12).reshape(2, 2, 3)
a3
array([[[ 0,  1,  2],
        [ 3,  4,  5]],

       [[ 6,  7,  8],
        [ 9, 10, 11]]])
a3[0,1,1] 
a3[1,1,2]
11
a3[[0,1],[1,1],[1,2]]
array([ 4, 11])

슬라이싱

  • 배열의 원소들을 범위로 조회한다.
  • ndarry[start : stop : step ]
    • start : 시작 인덱스. 기본값 0
    • stop : 끝 index. stop은 포함하지 않는다. 기본값 마지막 index
    • step : 증감 간격. 기본값 1

다차원 배열 슬라이싱

  • 각 축에 slicing 문법 적용
  • 2차원의 경우
    • arr [0축 slicing, 1축 slicing]
      • arr[:3, :]
    • , 로 축을 구분한 다중 슬라이싱 사용
  • 다차원의 경우
    • arr[0축 slicing, 1축 slicing, …, n축 slicing]
  • slicing과 indexing 문법은 같이 쓸 수 있다.

슬라이싱은 원본에 대한 View

  • slicing한 결과는 새로운 배열을 생성하는 것이 아니라 기존 배열을 참조한다.
  • slicing한 배열의 원소를 변경하면 원본 배열의 것도 바뀐다.
  • 배열.copy()
    • 배열을 복사한 새로운 배열 생성
    • 복사후 처리하면 원본이 바뀌지 않는다.
a = np.arange(30)
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, 24, 25, 26, 27, 28, 29])

1. ‘0 ~ 4’, step: - 1

a[:5]
array([0, 1, 2, 3, 4])
a[2:15:3]
array([ 2,  5,  8, 11, 14])
a[20:-1] # 마지막은 뺴고 조회
array([20, 21, 22, 23, 24, 25, 26, 27, 28])
a[:4] = 400
a
array([400, 400, 400, 400,   4,   5,   6,   7,   8,   9,  10,  11,  12,
        13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,
        26,  27,  28,  29])

2. 원본은 바꾸고 싶지 않을때 ‘ .copy( ) ‘를 사용한다

b = a[:4].copy()
print(b)
print(b[0])
b[0] = 500000
b
[500 400 400 400]
500





array([500000,    400,    400,    400])
a2 = np.arange(30).reshape(5, 6)
a2
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],
       [24, 25, 26, 27, 28, 29]])

3. slicing 을 통해 범위설정 조회가 가능하다.

a2[:3, 1:5]
array([[ 1,  2,  3,  4],
       [ 7,  8,  9, 10],
       [13, 14, 15, 16]])
print(a2[:,1])
print('-'*20)
print(a2[:,[1,4]])
print('-'*20)
print(a2[1,1:5])
print('-'*20)
print(a2[[1,-1],1:5])
[ 1  7 13 19 25]
--------------------
[[ 1  4]
 [ 7 10]
 [13 16]
 [19 22]
 [25 28]]
--------------------
[ 7  8  9 10]
--------------------
[[ 7  8  9 10]
 [25 26 27 28]]

boolean indexing

  • Index 연산자에 같은 형태(shape)의 Boolean 배열을 넣으면 True인 index의 값만 조회 (False가 있는 index는 조회하지 않는다.)
  • ndarray내의 원소 중에서 원하는 조건의 값들만 조회할 때 사용
    • ndarray는 element-wise 연산을 지원한다. 이를 이용해 boolean indexing으로 원하는 조건의 값들을 조회할 수 있다.
  • boolean indexing을 masking이라고도 한다.

넘파이 비교연산자

  • 파이썬의 and, or, not은 사용할 수 없다.
  • &: and연산
  • |: or 연산
  • ~: not 연산
  • 피연산자는 ( )로 묶어야 한다.
np.random.seed(0)
a = np.random.randint(100, size = 20) # 0 ~ 99 사이의 임의 정수 20개.
a
array([44, 47, 64, 67, 67,  9, 83, 21, 36, 87, 70, 88, 88, 12, 58, 65, 39,
       87, 46, 88])

1. a 에서 50 이상인 값들만 조회.

a[a > 50] # 원소별로 연산
array([64, 67, 67, 83, 87, 70, 88, 88, 58, 65, 87, 88])

2. ‘30 < a < 60’

a[(a > 30) & (a <60)]
array([44, 47, 36, 58, 39, 46])

3. 30 ~ 60 사이가 아닌것.( ‘ ~ ‘ 사용)

a[~((a > 30) & (a <60))]
array([64, 67, 67,  9, 83, 21, 87, 70, 88, 88, 12, 65, 87, 88])
a[(a <= 30) | (a >= 60)]
array([64, 67, 67,  9, 83, 21, 87, 70, 88, 88, 12, 65, 87, 88])
a2 = np.random.randint(100, size = (7,8))
a2
array([[82, 46, 99, 20, 81, 50, 27, 14],
       [41, 58, 65, 36, 10, 86, 43, 11],
       [ 2, 51, 80, 32, 54,  0, 38, 19],
       [46, 42, 56, 60, 77, 30, 24,  2],
       [ 3, 94, 98, 13, 40, 72, 19, 95],
       [72, 26, 66, 52, 67, 61, 14, 96],
       [ 4, 67, 11, 86, 77, 75, 56, 16]])
(a2 > 50).shape
(7, 8)

4. 다차원의 배열을 boolen indexing 을 하게되면 결과는 조건을 충족하는 값들로 1차원으로 반환한다.

a2[a2 > 50]
array([82, 99, 81, 58, 65, 86, 51, 80, 54, 56, 60, 77, 94, 98, 72, 95, 72,
       66, 52, 67, 61, 96, 67, 86, 77, 75, 56])

np.where()

  • True의 index 조회
    • np.where(boolean 배열) - True인 index를 반환
      • 반환타입: Tuple . True인 index들을 담은 ndarray를 축별로 Tuple에 묶어서 반환한다.
    • boolean연산과 같이사용하여 배열내에 특정 조건을 만족하는 값들을 index(위치)를 조회할 때 사용한다.
  • True와 False를 다른 값으로 변환
    • np.where(boolean 배열, True를 대체할 값, False를 대체할 값)
      • 배열내의 True를 True를 대체할 값으로 False를 False를 대체할 값 으로 변환한다.
r = np.where([True, False, True])
print(type(r), type(r[0]))
r
<class 'tuple'> <class 'numpy.ndarray'>





(array([0, 2]),)

1. 특정한 값으로 변환해서 출력한다.

r2 = np.where([True, False, True], '참', '거짓')
r2
array(['참', '거짓', '참'], dtype='<U2')
l = [
    [True, False, True],
    [False, False, True]  
]
r3 = np.where(l)
r3 # [0,0],[0,2],[1,2]
(array([0, 0, 1]), array([0, 2, 2]))
for a1, a2 in zip(r3[0], r3[1]):
    print(a1, a2 ,sep = ', ')
0, 0
0, 2
1, 2
np.random.seed(0)
a2 = np.random.randint(100, size = (5, 2, 3))
a2.shape
(5, 2, 3)

2. Boolean Indexing.

  • ( 5, 2, 3 )인 a2에서 70 이상인 값들 조회 ==> 조건이 True값들을 조회 ==> boolean indexing
a2[a2 >= 70]
array([83, 87, 70, 88, 88, 87, 88, 81, 77, 72, 80, 79])

3. np.where( )

  • 70 이상인 값들의 위치. == > 조건이 True인 값들의 위치(index) ====> np.where()
axis1, axis2, axis3 = np.where(a2 >= 70)
print(axis1)
print(axis2)
print(axis3)
[1 1 1 1 2 2 3 3 3 4 4 4]
[0 1 1 1 0 1 0 0 1 0 1 1]
[0 0 1 2 0 2 1 2 2 0 0 2]
for i, j, k in zip(axis1, axis2, axis3):
    print(a2[i, j, k], end = ', ')
83, 87, 70, 88, 88, 87, 88, 81, 77, 72, 80, 79, 

기타

  • np.any(boolean 배열)
    • 배열에 True가 하나라도 있으면 True 반환
    • 배열내에 특정조건을 만족하는 값이 하나 이상 있는지 확인할 때 사용
  • np.all(boolean 배열)
    • 배열의 모든 원소가 True이면 True 반환
    • 배열내의 모든 원소가 특정 조건을 만족하는지 확인 할 때 사용
np.any([True, False, False, False])
True
np.any(a2 == 99) # 99가 하나라도 있나?
np.any(a2 == 83)
# np.where(a==99)
False
np.all([True, True, False])
np.all([True, True, True])
True
np.all(a2 > 0)
np.all(a2 > 10)
# np.where(a2 <= 10)
False

배열의 형태(shape) 변경

  • 배열의 원소의 개수를 유지하는 상태에서 shape을 변경할 수있다.
    • 예) (16, ) -> (4,4) -> (2,2,4) -> (2,2,2,2), -> (4,4,1) -> (1, 16)

reshape()을 이용한 차원 변경

  • numpy.reshape(a, newshape) 또는 ndarray.reshape(newshape)
    • a: 형태를 변경할 배열
    • newshape : 변경할 형태 설정.
      • 원소의 개수를 유지하는 shape으로만 변환 가능하다.
      • 각 axis(축)의 size를 지정할 때 하나의 축의 size를 -1로 줄 수있다. 그러면 전체 size - 다른 축의 size합 을 -1로 지정한 axis 의 size로 지정한다.
    • 둘다 원본을 바꾸지 않고 reshape한 새로운 배열을 만들어 반환한다.
  • 내가 갖고있는 라이브러리의 차원과 가져다 쓰려고 하는 차원이 다를 경우

reshape 사용하여 차원을 맞추고 사용한다.

a = np.arange(20)
print(a.shape)
a
(20,)





array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19])
r1 = np.reshape(a, (2, 10))
print(r1.shape)
r1
(2, 10)





array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]])
r2 = a.reshape((4, 5)) # 튜플로 묶어서 입력.
r2 = a.reshape(4,5) # 가변인자로 입력 가능
print(r2.shape)
r2
(4, 5)





array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]])
r3 = a.reshape(2, 2, -1) # -1 은 너가 알아서 계산하라는 의미.
print(r3.shape)
r3
(2, 2, 5)





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

       [[10, 11, 12, 13, 14],
        [15, 16, 17, 18, 19]]])

차원 늘리기(확장)

  • Dummy axis(축)을 늘린다.
    • Dummy axis: size가 1인 axis 를 말한다.
  • reshape() 을 이용해 늘릴 수 있다.

  • indexer와 np.newaxis 변수를 이용해 늘린다.
    • ndarray[…, np.newaxis] 또는 ndarray[np.newaxis, …]
      • 맨앞 또는 맨 마지막에 dummy axis(축)을 늘릴때 사용한다.
      • 축을 늘리려는 위치에 np.newaxis를 지정하고 ... 으로 원본 배열의 shape을 유지함을 알려준다.

+ a

  • (5, 30) 30개의 속성을 가진 5 개수
  • 차원 늘리기 시 중간 축을 늘릴 경우는 거의 없다.
a.shape
# (20,1)
r1 = a.reshape(20, 1)
r1 = a.reshape(-1, 1)
print(r1.shape)
# (1, 20)
r1 = a.reshape(1, -1)
r1.shape
(20, 1)





(1, 20)
a2.shape # 다차원
# (1, 5, 2, 3)
r2 = a2.reshape(1, 5, 2, -1) # reshape로 다차원에서는 일일이 다 입력해야 함으로 번거러움 쓸 필요 딱히 없음.
# (5, 2, 3, 1)
r2 = a2.reshape(5, 2, 3, 1)
r2.shape
(5, 2, 3, 1)
a.shape
# (20,1)
a[... , np.newaxis].shape
# (1, 20)
a[np.newaxis, ...].shape
(1, 20)
a2.shape
# (1, 5, 2, 3)
a2[np.newaxis, ...].shape
# (5, 2, 3, 1)
a2[..., np.newaxis].shape
(5, 2, 3, 1)

1. ( 5, 2, 3 )인 a2의 2번축에 dummy axis를 추가.

r = np.expand_dims(a2, axis = 2) #(5, 2, 3)인 a2의 2번축에 dummy axis를 추가.
r = np.expand_dims(a2, axis = 0)
r = np.expand_dims(a2, axis = -1)
r.shape
(1, 5, 2, 3)

차원 줄이기(축소)

numpy.squeeze(배열, axis=None), 배열객체.squeeze(axis=None)

  • 배열에서 지정한 축(axis)을 제거하여 차원(rank)를 줄인다.
  • 제거하려는 축의 size는 1이어야 한다.
  • 축을 지정하지 않으면 size가 1인 모든 축을 제거한다.
    • (3,1,1,2) => (3,2)
a = np.arange(12).reshape(1, 2, 1, 2, 3, 1)
a.shape
(1, 2, 1, 2, 3, 1)
r1 = a.reshape(2, 2, 3)
r1.shape
(2, 2, 3)
r2 = a.squeeze() # reshape 한 새로운 배열을 생헝해서 반환.
r2.shape
(2, 2, 3)
r3 = a.squeeze(axis = 2) # (1, 2, 1, 2, 3, 1)에서 a[2]의 축을 제거.
r3.shape
(1, 2, 2, 3, 1)
r4 = a.squeeze(axis = [0,2]) # 한번에 하나씩 만 제거할 수 있다. (Error)
r4.shape

배열객체.flatten()

  • 다차원 배열을 1차원으로 만든다.
a.shape 
# a.reshape(12,)
a.reshape(-1)
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
print(a.shape)
r = a.flatten() # 다차원 배열을 1차원으로 만든다.
print(r.shape)
r
(1, 2, 1, 2, 3, 1)
(12,)





array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
a = np.arange(15).reshape(3, 5)
a.shape
(3, 5)
# 2차원 배열 => 0축 <-> 1축
# (3, 5) -> (5, 3)
r = a.T
r.shape
(5, 3)
a2 = np.arange(60).reshape(3, 4, 5)
a2.shape
(3, 4, 5)
# (5, 3, 4) # (2, 0, 1) // (0 => 1, 1 => 2 , 2 => 0), (0번 축을 1번 축으로, 1번 축을 2번 축으로, 2번 축을 0번 축으로)
r2 = np.transpose(a2, (2, 0, 1)) # 대상배열, 축을 어떻게 이동할지
r2.shape
(5, 3, 4)

배열 연산

벡터화 - 벡터 연산

  • 배열과 scalar 간의 연산은 원소단위로 계산한다.
  • 배열간의 연산은 같은 index의 원소끼리 계산 한다.
    • Element-wise(원소별) 연산 이라고도 한다.
    • 배열간의 연산시 배열의 형태(shape)가 같아야 한다.
    • 배열의 형태가 다른 경우 Broadcast 조건을 만족하면 연산이 가능하다.

배열과 스칼라간 연산

\[\begin{align} 10 - \begin{bmatrix} 1 \\ 2 \\ 3 \\ \end{bmatrix} = \begin{bmatrix} 10 - 1 \\ 10 - 2 \\ 10 - 3 \\ \end{bmatrix} = \begin{bmatrix} 9 \\ 8 \\ 7 \\ \end{bmatrix} \end{align}\] \[\begin{align} 10 \times \begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix} = \begin{bmatrix} 10\times1 & 10\times2 \\ 10\times3 & 10\times4 \\ \end{bmatrix} = \begin{bmatrix} 10 & 20 \\ 30 & 40 \end{bmatrix} \end{align}\]

배열 간의 연산

\(\begin{align} \begin{bmatrix} 1 \\ 2 \\ 3 \\ \end{bmatrix} + \begin{bmatrix} 10 \\ 20 \\ 30 \\ \end{bmatrix} = \begin{bmatrix} 1 + 10 \\ 2 + 20 \\ 3 + 30 \\ \end{bmatrix} = \begin{bmatrix} 11 \\ 22 \\ 33 \\ \end{bmatrix} \end{align}\)

\[\begin{align} \begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix} + \begin{bmatrix} 10 & 20 \\ 30 & 40 \\ \end{bmatrix} = \begin{bmatrix} 1+10 & 2+20 \\ 3+30 & 4+40 \end{bmatrix} = \begin{bmatrix} 11 & 22 \\ 33 & 44 \end{bmatrix} \end{align}\]

내적 (Dot product) 연산

  • @ 연산자 또는 numpy.dot(벡터/행렬, 벡터/행렬) 함수 사용

1차원 배열(벡터)간의 내적

  • 같은 index의 원소끼리 곱한뒤 결과를 모두 더한다.
  • 벡터간의 내적의 결과는 스칼라가 된다.
  • $ x \cdot y $ 또는 $x^T y$로 표현
  • 조건
    • 두 벡터의 차원(원소의개수)가 같아야 한다.
    • 앞의 벡터는 행벡터 뒤의 벡터는 열벡터 이어야 한다.
      • numpy 에서는 vector 끼리 연산시 앞의 벡터는 행벡터로 뒤의 벡터는 열벡터로 인식해 처리한다.
\[\begin{align} x = \begin{bmatrix} 1 \\ 2 \\ 3 \\ \end{bmatrix} ,\;\;\; y = \begin{bmatrix} 4 \\ 5 \\ 6 \\ \end{bmatrix} \end{align}\] \[\begin{align} x^T y = \begin{bmatrix} 1 & 2 & 3 \end{bmatrix} \begin{bmatrix} 4 \\ 5 \\ 6 \\ \end{bmatrix} = 1 \times 4 + 2 \times 5 + 3 \times 6 = 32 \end{align}\]

행렬간의 내적 (행렬 곱)

  • 앞 행렬의 행과 뒤 행렬의 열간에 내적을 한다.
  • 행렬과 행렬을 내적하면 그 결과는 행렬이 된다.
  • 앞 행렬의 열수뒤 행렬의 행수가 같아야 한다.
  • 내적의 결과의 형태(shape)는 앞행렬의 행수와 뒤 행렬의 열의 형태를 가진다.
    • (3 x 2)와 (2 x 5) = (3 x 5)
    • (1 x 5)와 (5 x 1) = (1 x 1)
\[\begin{align} A = \begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \end{bmatrix} \end{align}\] \[\begin{align} B = \begin{bmatrix} 1 & 2 \\ 3 & 4 \\ 5 & 6 \end{bmatrix} \end{align}\] \[\begin{align} A\cdot B = \begin{bmatrix} 1\times 1 + 2\times 3 + 3 \times 5 & 1\times 2 + 2\times 4 + 3 \times 6 \\ 4\times 1 + 5\times 3 + 6 \times 5 & 4\times 2 + 5\times 4 + 6 \times 6 \end{bmatrix} = \begin{bmatrix} 22 & 28 \\ 49 & 64 \end{bmatrix} \end{align}\]

1. 안쪽이 같으면 계산이 가능하고, 결과는 바깥쪽 행열이다.

x = np.array([1, 2, 3])
y = np.array([4, 5, 6])

r1 = x * y
result = np.sum(r1)
result
32
x @ y, np.dot(x, y)
(32, 32)
A = np.arange(1, 7).reshape(2, 3)
B = np.arange(1, 7).reshape(3, 2)
A.shape, B.shape
((2, 3), (3, 2))
A @ B
array([[22, 28],
       [49, 64]])
B @ A
array([[ 9, 12, 15],
       [19, 26, 33],
       [29, 40, 51]])

내적의 예

가중합

가격: 사과 2000, 귤 1000, 수박 10000
개수: 사과 10, 귤 20, 수박 2
총가격?
2000*10 + 1000 * 20 + 10000 * 2

f = np.array([2000, 1000, 10000])
cnt = np.array([10, 20, 2])
f @ cnt, np.dot(f, cnt)
(60000, 60000)
cnt2 = np.array([[10, 20, 2],
                [5, 15, 10],
                [10, 10, 10],
                [5, 6, 7],
                [10, 1, 1]])

cnt2.shape
(5, 3)

2. f 의 행과 열을 바꿔준다.

f2 = f[..., np.newaxis]
f2.shape
f2
array([[ 2000],
       [ 1000],
       [10000]])
cnt2 @ f2
array([[ 60000],
       [125000],
       [130000],
       [ 86000],
       [ 31000]])
np.dot(cnt2, f2)
array([[ 60000],
       [125000],
       [130000],
       [ 86000],
       [ 31000]])

기술통계함수

  • 통계 결과를 계산해 주는 함수들
  • 구문
    1. np.전용함수(배열)
      • np.sum(x)
    2. 일부는 배열.전용함수() 구문 지원
      • x.sum() - 공통 매개변수
      • axis=None: 다차원 배열일 때 통계값을 계산할 axis(축)을 지정한다. None(기본값)은 flatten후 계산한다.
  • 배열의 원소 중 누락된 값(NaN - Not a Number) 있을 경우 연산의 결과는 NaN으로 나온다.
  • 안전모드 함수
    • 배열내 누락된 값(NaN)을 무시하고 계산
  • https://docs.scipy.org/doc/numpy-1.15.1/reference/routines.statistics.html

image.png

np.random.seed(0)
a = np.random.choice(100, size = 10) # 0 ~ 99 정수
a = a.astype('float32')
a
array([44., 47., 64., 67., 67.,  9., 83., 21., 36., 87.], dtype=float32)
np.sum(a), a.sum()
(525.0, 525.0)
a.max(), a.argmax(), a.min(), a.argmin()
(87.0, 9, 9.0, 5)
a.mean(), np.mean(a)
(52.5, 52.5)
np.mean([80, 90, 100])
90.0
np.average([80, 90, 100], weights = [2, 2, 1])
88.0

1. 결측치 대입

a[1] = np.nan 
a
array([44., nan, 64., 67., 67.,  9., 83., 21., 36., 87.], dtype=float32)

2. 결측치의 개수 확인.

np.sum(np.isnan(a)) 
1
a.sum(), a.max(), a.mean()
(nan, nan, nan)

3. a.nansum( ) 은 불가능

np.nansum(a), np.nanmax(a), np.nanmean(a)
(478.0, 87.0, 53.11111)
b = np.arange(1, 13).reshape(3, 4)
print(b.shape)
b
(3, 4)





array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12]])

4. axis를 지정하지 않으면 전체 기준 통계량을 계산한다.

b.sum(), b.mean(), b.max()
(78, 6.5, 12)

5. axis = 0 : axis 1은 같고, axis 2의 index는 다른 값끼리 계산.

b.sum(axis = 0)
array([15, 18, 21, 24])
b.sum(axis = 1)
array([10, 26, 42])
c = np.arange(1, 13).reshape(2, 2, 3)
c
array([[[ 1,  2,  3],
        [ 4,  5,  6]],

       [[ 7,  8,  9],
        [10, 11, 12]]])
c.sum(axis = 0)
array([[ 8, 10, 12],
       [14, 16, 18]])

6. 지정한 axix의 index는 다르고 나머지 axis의 index는 같은 값들끼리 계산.

c.sum(axis = 1) 
array([[ 5,  7,  9],
       [17, 19, 21]])

브로드캐스팅

  • 사전적의미 : 퍼트린다. 전파한다.
  • 형태(shape)가 다른 배열 연산시 배열의 형태를 맞춰 연산이 가능하도록 한다.
    • 모든 형태를 다 맞추는 것은 아니고 조건이 맞아야 한다.
  • 조건
    1. 두 배열의 축의 개수가 다르면 작은 축의개수를 가진 배열의 형태(shape)의 앞쪽을 1로 채운다.
      • (2, 3) + (3, ) => (2, 3) + (1, 3)
    2. 두 배열의 차원 수가 같지만 각 차원의 크기가 다른 경우 어느 한 쪽에 1이 있으면 그 1이 다른 배열의 크기와 일치하도록 늘어난다.
      • 1 이외의 나머지 축의 크기는 같아야 한다.
      • 늘리면서 원소는 복사한다.
      • (2, 3) + (1, 3) => (2, 3)+(2, 3)

image.png

x = np.array([1, 2, 3])
y = np.array([2])
x.shape, y.shape
((3,), (1,))
x + y
array([3, 4, 5])

1개 이상인 사이즈는 사이즈가 다르면 계산 안됨.

사이즈가 다른데 둘중 하나가 1 있으면 계산 가능.

댓글남기기