HOWTO · Pandas
Pandas에서 함수 벡터화
이 튜토리얼은 pandas에서 함수를 벡터화하는 방법을 보여줍니다.
이 페이지의 내용
pandas에서 함수를 벡터화하려면 먼저 전체 Series 또는 NumPy 배열을 받는 연산으로 계산식을 다시 작성하세요. 이렇게 하면 보통 각 값마다 Python 함수를 한 번씩 호출하지 않아도 됩니다. 호환되는 배열 연산으로 로직을 표현할 수 없다면 요소별 변환을 명확하게 나타내는 Series.map을 사용하세요. Series.apply도 값마다 함수를 적용하는 방법이지만, 벡터화로 전환해 주는 기능은 아닙니다.
Pandas에서 함수 벡터화
이 예제에서는 급여 조정에 사용자 정의 함수와 배열 연산식을 적용해 비교합니다. 데이터가 코드 안에서 직접 만들어지므로 외부 파일이 필요하지 않습니다. 예제를 실행해 보세요.
이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.
import pandas as pd
pay = pd.Series([1000.0, 2000.0, 3000.0], name="pay")
def add_tax(value):
return value * 1.05 + 1
mapped = pay.map(add_tax)
vectorized = pay * 1.05 + 1
applied = pay.apply(add_tax)
reference = pd.Series([1051.0, 2101.0, 3151.0], name="pay")
print(vectorized.tolist())
print(mapped.equals(vectorized))
print(applied.equals(vectorized))
print(vectorized.equals(reference))
정상적으로 실행하면 다음이 출력됩니다.
[1051.0, 2101.0, 3151.0]
True
True
True
pandas Series의 벡터화란
pandas Series에는 레이블이 지정된 값이 저장됩니다. pay * 1.05 + 1과 같은 식은 인덱스를 유지하면서 Series 전체에 산술 연산을 적용합니다. 이는 배열 중심 코드입니다. 코드에서 각 값마다 add_tax를 직접 호출하는 대신 pandas와 그 기반 라이브러리가 데이터에 연산을 적용합니다.
벡터화는 연산을 표현하고 처리하는 방식을 가리키며, 특정 구현을 보장하지는 않습니다. pandas 연산도 내부적으로 반복문을 사용할 수 있으며 SIMD 명령어를 사용한다고 단정해서는 안 됩니다. 실질적인 차이는 호환되는 Series 또는 NumPy 연산을 사용하면 항목마다 Python 수준의 함수를 호출하지 않아도 될 수 있다는 점입니다. 실제 속도는 연산, 데이터 크기, dtype, 실행 환경에 따라 달라집니다.
Series.map으로 요소별 함수 적용하기
사용자 정의 스칼라 함수가 변환을 가장 명확하게 표현한다면 Series.map을 사용하세요. 예제의 pay.map(add_tax)는 각 값에 add_tax를 호출하고 입력 인덱스를 유지한 Series를 반환합니다. 함수는 스칼라 하나를 받아 변환된 스칼라 하나를 반환해야 합니다. 배열 연산식으로 바로 나타낼 수 없는 사용자 정의 규칙이나 조회 작업에 유용한 방식입니다.
고정된 매핑에는 딕셔너리를 Series.map에 전달할 수도 있습니다. 일치하는 키가 없는 값은 결측값이 되므로, 매핑이 가능한 입력을 모두 포함하지 않을 때는 이 동작을 확인하세요. 단순한 산술 계산이라면 연산을 직접 나타내고 스칼라 Python 작업을 요소별 호출로 감싸지 않는 Series 식을 우선 사용하세요.
함수를 배열 연산으로 다시 작성하기
add_tax 함수는 value * 1.05 + 1을 계산합니다. Series에서 곱셈과 덧셈을 지원하므로 같은 규칙을 pay * 1.05 + 1로 나타낼 수 있습니다. 함수를 유용하게 벡터화하는 방법은 원래 Python 함수를 반복해서 적용하는 대신 전체 배열에서 작동하는 연산으로 로직을 표현하는 것입니다.
DataFrame 열에도 같은 식을 적용할 수 있습니다. 열을 Series로 선택한 뒤 df["TotalPay"] * 1.05 + 1처럼 계산하세요. 결과를 원본 데이터와 함께 보관하려면 새 열에 할당하면 됩니다. pandas는 할당이나 Series 간 산술 연산을 할 때 인덱스를 기준으로 Series를 정렬하므로, 따로 만든 데이터를 결합할 때는 인덱스가 서로 맞는지 확인하세요.
벡터화, map, apply 중 선택하기
해당 dtype에서 연산을 지원한다면 Series 또는 NumPy 식을 선택하세요. 값별 사용자 정의 변환이나 조회에는 Series.map을 사용하세요. 스칼라 함수가 필요하고 map으로 작업을 명확하게 표현하기 어렵다면 Series.apply를 사용할 수 있습니다. map과 일반적인 Series apply 경로는 모두 개별 값마다 Python 로직을 호출합니다. 둘 중 어느 것도 스칼라 함수를 자동으로 네이티브 벡터화 코드로 바꾸지는 않습니다.
평균을 구할 때는 반복문이나 Series.apply로 각 스칼라에 np.mean을 따로 호출하지 마세요. Series 전체에서 하나의 결과를 계산하려면 축약 연산인 pay.mean() 또는 numpy.mean(pay)를 사용하세요. 축약 연산은 변환과 결과의 의미가 다릅니다. 입력 행마다 값 하나를 반환하는 대신 집계 결과 하나를 반환합니다.
결과를 확인하고 신중하게 벤치마크하기
다시 작성한 식을 더 큰 데이터에 적용하기 전에 대표적인 입력으로 간단한 기준 계산과 비교하세요. 예제에서는 map과 apply로 얻은 값이 벡터화된 값과 일치하는지 확인한 다음, 식의 결과를 직접 지정한 기준 Series와 비교합니다. 동등성 검사에는 Series 인덱스도 포함되므로 값뿐 아니라 정렬 차이도 찾는 데 도움이 됩니다.
결측값과 dtype에 따라 동작이 달라질 수 있습니다. 예를 들어 산술 연산은 대체로 결측값을 전파하지만 사용자 정의 함수는 다르게 처리할 수 있습니다. 정수, 부동 소수점, nullable, object 열도 서로 다르게 동작할 수 있습니다. 방법을 비교하기 전에 입력 dtype을 확인하고 결측값을 어떻게 처리할지 정하세요.
작업에서 성능이 중요할 때만 벤치마크하세요. 같은 입력에 대해 동등한 계산을 비교하고, 필요에 따라 준비 실행을 한 뒤 측정을 반복하며, 측정 방법과 환경을 함께 기록하세요. 하드웨어, pandas 및 NumPy 버전, 데이터 크기, dtype에 따라 시간이 달라지므로 작은 예제만으로 일반적인 속도 향상을 입증할 수는 없습니다.