파이썬 넘파이(Numpy) 함수 총정리3 : 통계, 집계, 산술, 수학, 행렬 연산

넘파이(Numpy) 배열을 사용하는 가장 본질적인 이유는 무엇일까요? 바로 강력한 수치 연산 기능 때문일 것입니다. 파이썬의 기본 리스트로는 구현하기 복잡하고 느린 계산도 넘파이에서는 단 한 줄의 코드로, 그것도 엄청난 속도로 처리할 수 있습니다. 

이 글에서는 넘파이 함수 총정리 제 3탄으로, 데이터 분석과 머신러닝의 기초가 되는 통계, 집계, 산술 연산부터 수학 및 행렬 연산까지 핵심 함수들을 예제와 함께 정리해 보도록 하겠습니다. 

넘파이 통계, 집계, 산술, 수학, 행렬 연산 함수
넘파이(Numpy) 통계, 집계, 산술, 수학, 행렬 연산 함수


01. 통계 및 집계 연산 함수

넘파이 배열은 수만 개의 데이터도 순식간에 계산해냅니다. 여기서 가장 중요한 개념은 축(axis)입니다. 축(axis)을 지정하면 내가 원하는 방향의 축(axis)을 기준으로 계산을 하게 되고, 축(axis)을 지정하지 않는다면 전체요소를 대상으로 계산을 진행합니다.

(참고) 배열 a의 통계 및 집계 함수를 사용할 때, np.sum(a) 처럼 함수를 사용해도 되고, 배열에 메소드가 있는 경우 a.sum( ) 처럼 메소드를 사용해도 결과는 동일 합니다. 


1) sum( ) : 합계
  • np.sum(a, axis=None, keepdims=False, where=True, initial=0
  • a.sum(axis=None, keepdims=False, where=True, initial=0)
    - a : 입력 배열 
    axis : 어느 축을 기준으로 계산할지 지정 (기본값 : None, 전체요소 기준)
    - keepdims : True로 설정하면 결과 배열의 차원을 원본과 동일하게 유지함
    where : 조건이 참(True)인 요소만 계산에 포함시킴 
    initial : 시작값을 지정함 (결과 = initial + 배열 요소의 합)

2) mean( ) : 평균
  • np.mean(a, axis=None, keepdims=False, where=True)
  • a.mean(axis=None, keepdims=False, where=True)

3) std( ) : 표준편차
  • np.std(a, axis=None, keepdims=False, where=True, ddof=0)
  • a.std(axis=None, keepdims=False, where=True, ddof=0)
    ddof : 계산시 분모를 N-ddof로 나눕니다. (기본값 : 0)
    - (ddof=0은 모표준편차, ddof=1은 표본표준편차)

4) var( ) : 분산
  • np.var(a, axis=None, keepdims=False, where=True, ddof=0)
  • a.var(axis=None, keepdims=False, where=True, ddof=0)
    ddof : 계산시 분모를 N-ddof로 나눕니다. (기본값 : 0)
    - (ddof=0은 모분산, ddof=1은 표본분산)

5) min( ) : 최소값
  • np.min(a, axis=None, keepdims=False, where=True, initial=None)
  • a.min(axis=None, keepdims=False, where=True, initial=None)
    initial : 시작값을 지정함 (값 비교시 포함됨)
    - where 조건을 사용할 때는 initial 값을 필히 지정해주어야 됩니다.

6) max( ) : 최대값
  • np.max(a, axis=None, keepdims=False, where=True, initial=None)
  • a.max(axis=None, keepdims=False, where=True, initial=None)
    initial : 시작값을 지정함 (값 비교시 포함됨)
    - where 조건을 사용할 때는 initial 값을 필히 지정해주어야 됩니다.

    a = np.array([[1, 2], [3, 4], [5, 6]])
    
    print(a.sum())                                 # 결과: 21
    print(a.mean())                                # 결과: 3.5
    print(a.std())                                 # 결과: 1.70782512
    print(a.var())                                 # 결과: 2.91666665
    print(a.min())                                 # 결과: 1
    print(a.max())                                 # 결과: 6
    
    print(a.sum(axis=0))                           # 결과: [9 12]
    print(a.sum(axis=1))                           # 결과: [3 7 11]
    print(a.sum(axis=1, keepdims=True))            # 결과: [[3][7][11]]
    print(a.sum(axis=1, where=(a > 5)))            # 결과: [0 0 6]
    
    print(a.max(axis=0))                           # 결과: [5 6]
    print(a.max(axis=1))                           # 결과: [2 4 6]
    print(a.max(axis=1, keepdims=True))            # 결과: [[2][4][6]]
    print(a.max(axis=1, where=(a<5), initial=9))   # 결과: [9 9 9]
    print(a.max(axis=1, where=(a<5), initial=-9))  # 결과: [2 4 -9]
    print(a.max(axis=1, where=(a<5)))              # Error 발생


    02. 배열의 산술 연산 함수

    넘파이 배열의 산술 연산에서는 브로드캐스팅(Broadcasting) 개념을 알아둘 필요가 있습니다. 

    [브로드캐스팅] Broadcasting이란 모양(Shape)이 다른 배열들 간에 산술 연산을 가능하게 해주는 규칙으로, 두 배열 중 한쪽 배열의 차원 크기가 1일 때, 같은 값으로 차원 크기를 확장시켜 연산을 수행합니다. 


    1) 배열과 스칼라 연산

    • 배열과 스칼라 연산시 배열의 각 요소에 스칼라 값이 적용되어 연산됩니다. 

    a = np.array([[1, 2], [98, 99]])
    
    print(a + 10)    # 결과(덧셈)   : [[ 11  12][108 109]]
    print(a - 10)    # 결과(뺄셈)   : [[ -9  -8][ 88  89]]
    print(a * 10)    # 결과(곰셈)   : [[ 10  20][980 990]]
    print(a / 10)    # 결과(나눗셈) : [[0.1 0.2][9.8 9.9]]
    print(a % 10)    # 결과(나머지) : [[  1   2][  8   9]]
    print(a // 10)   # 결과(몫)     : [[  0   0][  9   9]]
    print(a ** 2)    # 결과(제곱)   : [[  1   4][9604 9801]]
    


    2) 배열과 배열 연산

    1. np.add(a, b) : 더하기 ( * )
    2. np.subtract(a, b) : 빼기( - )
    3. np.multiply(a, b) : 곱하기( * ) 
    4. np.divide(a, b) : 나누기( / )
    5. np.floor_divide(a, b) : 몫( // )
    6. np.remainder(a, b) : 나머지( % )
    7. np.power(a, b) : 거듭제곱( ** )
    • 같은 모양(shape)의 배열과 배열간 연산을 하게되면, 각 배열의 요소의 값을 위치에 따라 1:1로 매칭하여 연산하게 됩니다. 연산기호를 사용해도 되고 함수를 사용해도 됩니다. 
    • 만약 다른 모양(shape)이지만, 한쪽 배열의 차원의 크기가 1인 경우 브로드캐스팅(broadcasting)*이 일어나 같은 값으로 확장하여 연산하게 됩니다. 

    a1 = np.array([[11, 12, 13], [14, 15, 16]])
    a2 = np.array([[ 1,  2,  3], [ 4,  5,  6]])
    a3 = np.array([10])
    a4 = np.array([[10]])
    a5 = np.array([[10],[100]])
                       
    print(a1 + a2)   # 결과: [[12 14 16][18 20 22]]
    print(a1 - a2)   # 결과: [[10 10 10][10 10 10]]
    
    print(a2 + a3)   # 결과: [[11 12 13][14 15 16]]    (브로드캐스팅)
    print(a2 + a4)   # 결과: [[11 12 13][14 15 16]]    (브로드캐스팅)
    print(a2 + a5)   # 결과: [[11 12 13][104 105 106]] (브로드캐스팅)

    • 만약 나눗셈을 할 때, 분모에 0이 있는 경우를 나눗셈 연산에서 제외하고 싶을 때는 아래와 같이 해주어야 합니다. 
    a1 = np.array([[10, 12, 14], [14, 15, 16]])
    a2 = np.array([[ 1,  0,  2], [ 7,  5,  0]])
    
    result = np.zeros_like(a1, dtype=float)
    np.divide(a1, a2, out=result, where=(a2!=0))
    
    print(a1/a2)                      # 결과: [[10. inf 7.][2. 3. inf]]
    print(np.where(a2!=0, a1/a2, 0))  # 결과: [[10.  0. 7.][2. 3.  0.]]
    print(result)                     # 결과: [[10.  0. 7.][2. 3.  0.]]
    


    03. 수학 함수

    넘파이 수학 함수는 배열 전체에 각 요소별로 적용됩니다. 


    1) 절대값과 지수 및 로그 함수

    1. np.abs(array) : 각 요소에 절대값을 적용합니다. 
    2. np.exp(array) : 각 요소에 밑이 e인 지수 함수(ex)를 적용합니다.
    3. np.log(array) : 각 요소에 자연로그(logx = ln x)를 적용합니다. 
    4. np.log10(array) : 각 요소에 상용로그(log10 x)를 적용합니다.


    2) 삼각 함수

    1. np.sin(array) : 각 요소에 라디안 값을 기준으로 sin(x)를 적용합니다. 
    2. np.cos(array: 각 요소에 라디안 값을 기준으로 cos(x)를 적용합니다. 
    3. np.tan(array: 각 요소에 라디안 값을 기준으로 tan(x)를 적용합니다. 


    3) 올림과 내림

    1. np.floor(array) : 각 요소에 내림을 적용합니다. (작거나 같은 최대 정수)
    2. np.ceil(array) : 각 요소에 올림을 적용합니다. (크거나 같은 최소 정수)
    3. np.round(array, decimals=0) : 각 요소에 반올림을 적용합니다. (Round half to even 적용)
      (주의사항) 반올림할 자리가 정확히 절반일 때는, 통계적 오차를 줄이기 위해, 가장 가까운 "짝수"쪽으로 반올림합니다. (ex, decimals=0인 경우에는 끝짜리가 .5 일 때)
      - decimals : 반올림할 소수점 위치 (기본값 0)
      • 양수 : 소수점 아래 n번째 자리까지 유지
      • 음수 : 소수점 위(10, 100의 자리 등)에서 반올림 

    a = np.array([[1.3, 1.4, 1.5, 1.6],[-1.3, -1.4, -1.5, -1.6]])
    b = np.array([1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5])
    
    print(np.floor(a))                # 결과: [[ 1.  1.  1.  1.]
                                      #        [-2. -2. -2. -2.]]
    
    print(np.ceil(a))                 # 결과: [[ 2.  2.  2.  2.]
                                      #        [-1. -1. -1. -1.]]
    
    print(np.round(a, decimals=0))    # 결과: [[ 1.  1.  2.  2.]
                                      #        [-1. -1. -2. -2.]]
    
    print(np.round(b, decimals=0))    # 결과: [2. 2. 4. 4. 6. 6. 8. 8.]
    


    04. 행렬 연산

    1) 수학 행렬의 곱셈

    a 행렬(l x m)과 b 행렬(m x n)의 행렬 곱셈은 아래의 3가지 방법 중 하나를 선택하여 사용하시면 됩니다.
    1. np.dot(a, b
    2. a.dot(b) 
    3. a @

    a = np.array([[1, 2, 3], 
                  [4, 5, 6]])
    b = np.array([[1, 4], 
                  [2, 5], 
                  [3, 6]])
    
    print(a @ b)  # 결과: [[14 32]
                  #        [32 77]]
    


    Previous Post
    No Comment
    Add Comment
    comment url