ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Pandas, NumPy] 일괄 계산을 위한 판다스, 넘파이 브로드캐스팅 알아보기
    Python/Pandas, Numpy 2023. 4. 24. 16:51
    반응형

    일괄 계산을 위한 판다스, 넘파이 브로드캐스팅 알아보기


    파이썬(Python)의 대표적인 패키지 판다스(Pandas)와 넘파이(NumPy)에서는 브로드캐스팅(Broadcasting)이라는 연산이 있습니다. 다양한 파이썬 코딩 강의 자료에서 이런 연산을 다루지만, 명확한 정의는 잘 가르쳐주지 않아서 무엇인지 궁금하다면 판다스 혹은 넘파이 공식 문서의 설명을 읽어보는것이 좋겠습니다.

     

     

    판다스 공식 문서에서는 브로드캐스팅을 고차원저차원 객체 사이의 연산으로 정의합니다.

     

     

    조금 더 친숙한 설명을 하자면, 브로드캐스팅은 우리가 고등수학에서 배웠던 행렬 연산과 같다고 볼 수 있습니다. 행렬의 연산에서 (1, 2, 3) + 99 = (100, 101, 102) 가 되는것과 같은 계산입니다.

     

    • 우리는 이 계산을 할 때, 1 + 99와 2 + 99, 3 + 99를 하나씩 계산했지만,
    • 컴퓨터는 이걸 단 한번의 계산으로 처리할 수 있는 능력이 있습니다.

     

    그렇다면, 브로드캐스팅을 잘 쓴다면 식을 간결하게 만드는건 물론이고, 작업 속도를 효과적으로 늘릴 수도 있다는 말이죠.

    넘파이는 행렬을 다루는 패키지이기 때문에 당연히 브로드캐스팅을 지원할거라 예상할 수 있지만, 판다스도 같은 방법으로 브로드캐스팅을 지원한다는건 놀라운 사실입니다. 그런데, 잘 생각해보면 엑셀에서 열 단위 연산을 할 수 있지요? 그렇게 본다면 판다스에서 브로드캐스팅을 지원하는건 당연한 이야기네요.

     

    판다스의 브로드캐스팅


    판다스에서 브로드캐스팅을 쓰는 계산은 간단합니다. 우리가 흔히 쓰는 연산자를 그대로 쓰면 되거든요. 아래에 간단한 예시를 소개해 보겠습니다.

     

     

    import pandas as pd
    
    df = pd.DataFrame(
        {
            "one": [9, 8, 7],
            "two": [4, 2, 6],
            "three": [7, 4, 1]
        },
        index=["a", "b", "c"]
    )

     

     

    df
      one two three
    a 9 4 7
    b 8 2 4
    c 7 6 1

     

     

    # 예제 1: 판다스 브로드캐스팅 (2차원 + 0차원)
    df + 1025
      one two three
    a 1034 1029 1032
    b 1033 1027 1029
    c 1032 1031 1026

     

     

    # 예제 2: 판다스 브로드캐스팅 (2차원 + 1차원)
    df - [1, 2, 3]
      one two three
    a 8 2 4
    b 7 0 1
    c 6 4 -2

     

     

    이렇게 판다스에서는 차원의 제약 없이 연산을 할 수 있으며, 그 속도도 빠릅니다. 만약 이런 계산을 요소 하나하나를 집어서 계산을 하려고 했다면, 아래와 같은 코드를 적어야 했을겁니다.

     

     

    # 예제 1을 반복문으로 계산하기
    for i in df:
        for j in df[i]:
            print(j + 1025, end=' ')
    
        print()
    1034 1033 1032 
    1029 1027 1031 
    1032 1029 1026 

     

     

    그리고, 단순한 계산뿐만 아니라 일치 여부 확인 등의 조금 더 복잡한 작업에서도 브로드캐스팅을 활용할 수 있습니다. 예를 들어, 앞서 살펴본 df 데이터프레임에서 숫자 2 를 찾고 싶다면 어떻게 할까요? 반복문으로 해결할 수도 있지만, 우리는 간단하게 일치 여부를 확인하는 연산자인 == 를 이용할 수도 있습니다.

     

     

    # 예제 3: 일치 여부 확인 (판다스)
    df == 2
      one two three
    a False False False
    b False True False
    c False False False

     

    넘파이의 브로드캐스팅


    이러한 브로드캐스팅은 판다스뿐만 아니라, 넘파이에서도 이용할 수 있다고 글머리에 알려드렸죠. 넘파이에서도 똑같이 연산자를 이용한다면 브로드캐스팅 연산을 할 수 있습니다. 다만, 판다스와 넘파이는 자료형의 특성상 축의 방향(axis)가 다르기 때문에, 이 부분은 주의깊게 살펴보셔야 합니다.

     

     

    import numpy as np
    
    arr = np.array(
        [
            [9, 8, 7],
            [4, 2, 6],
            [7, 4, 1]
        ]
    )

     

     

    arr
    array([[9, 8, 7],
           [4, 2, 6],
           [7, 4, 1]])

     

     

    # 예제 1: 넘파이 브로드캐스팅 (2차원 + 0차원)
    arr + 1025
    array([[1034, 1033, 1032],
           [1029, 1027, 1031],
           [1032, 1029, 1026]])

     

     

    # 예제 2: 넘파이 브로드캐스팅 (2차원 + 1차원)
    arr - [1, 2, 3]
    array([[ 8,  6,  4],
           [ 3,  0,  3],
           [ 6,  2, -2]])

     

     

    # 예제 3: 일치 여부 확인 (넘파이)
    arr == 2
    array([[False, False, False],
           [False,  True, False],
           [False, False, False]])

     

     

    이렇게 브로드캐스팅을 이용하면 코드를 짜는 수고와 계산하는 속도가 한결 빨라집니다. 다만, 브로드캐스팅을 사용할 때는 제한이 하나 있는데요, 바로 행렬의 계산과 같은 축 길이의 제한입니다.

     

    • (4*3) 배열과 (1*3) 배열의 연산: 가능
    • (2*9) 배열과 (2*3) 배열의 연산: 불가능
    • (8*2) 배열과 단일 숫자의 연산: 가능

     

    이렇게 규칙을 표현할 수 있는데, 이걸 정리해서 말하자면 아래와 같은 규칙입니다.

     

     

    계산할 대상에서 후행(가장 오른쪽) 차원의 길이는 같거나, 하나가 1이어야 합니다.


    자료 참고

    반응형

    댓글

문의: jwkang3929@naver.com