import numpy as np
rng = np.random.default_rng()집계: 최소값, 최대값 그리고 그 밖의 모든 것
데이터 세트를 분석할 때 가장 먼저 하는 일은 다양한 요약 통계량(summary statistics)을 계산하는 것입니다. 평균과 표준편차는 데이터의 전반적인 특징을 요약해 주는 가장 대표적인 지표입니다. 하지만 이 외에도 합계, 곱, 중앙값, 최소/최대값, 분위수 등 다양한 집계 방식이 유용하게 쓰입니다.
NumPy는 배열 데이터를 빠르게 처리할 수 있는 다양한 내장 집계 함수를 제공합니다. 이번 섹션에서는 그중 주요 함수들을 직접 사용해 보겠습니다.
배열의 값 합산하기
가장 간단한 예로, 배열에 담긴 모든 값의 합계를 구해 보겠습니다. 파이썬에서는 기본 내장 함수인 sum()을 사용할 수 있습니다.
L = rng.random(100)
sum(L)NumPy의 sum() 함수 역시 사용법은 매우 비슷하며, 위와 같은 간단한 경우 결과도 동일합니다.
np.sum(L)하지만 NumPy 버전은 내부적으로 컴파일된 코드를 실행하기 때문에 계산 속도가 훨씬 빠릅니다.
big_array = rng.random(1000000)
%timeit sum(big_array)
%timeit np.sum(big_array)한 가지 주의할 점은 파이썬의 sum과 NumPy의 np.sum이 완전히 똑같지는 않다는 사실입니다. 이 때문에 가끔 혼란이 생기기도 합니다. 특히 선택적 인자(optional arguments)의 의미가 서로 다릅니다. 예를 들어 sum(x, 1)은 합계를 1부터 시작해 더하라는 뜻이지만, np.sum(x, 1)은 첫 번째 축(axis 1)을 따라 더하라는 뜻입니다. 또한 np.sum은 다차원 배열의 구조를 완벽히 이해하고 작동합니다.
최소값과 최대값
파이썬에는 배열의 최소값과 최대값을 찾는 min()과 max() 함수가 기본으로 내장되어 있습니다.
min(big_array), max(big_array)NumPy에서도 동일한 기능을 하는 함수를 제공하며, 역시 실행 속도가 훨씬 빠릅니다.
np.min(big_array), np.max(big_array)%timeit min(big_array)
%timeit np.min(big_array)min, max, sum을 비롯한 대부분의 NumPy 집계 함수는 배열 객체에서 직접 메서드 형태로 호출할 수도 있습니다.
print(big_array.min(), big_array.max(), big_array.sum())NumPy 배열을 다룰 때는 가능하면 항상 NumPy에서 제공하는 집계 함수를 사용하는 것이 좋습니다.
다차원 집계
집계 연산은 행이나 열 단위로 수행해야 할 때가 많습니다. 다음과 같은 2차원 배열이 있다고 가정해 봅시다.
M = rng.integers(0, 10, (3, 4))
print(M)인자를 생략하면 NumPy 집계 함수는 다차원 배열의 모든 요소에 대해 연산을 수행합니다.
M.sum()연산을 수행할 축(axis)을 지정할 수도 있습니다. 예를 들어 axis=0을 지정하면 각 열 내에서 최소값을 찾습니다.
M.min(axis=0)이 결과는 네 개의 열에 각각 대응하는 네 개의 최소값을 반환합니다.
마찬가지로 각 행 내에서 최대값을 찾을 수도 있습니다.
M.max(axis=1)여기서 축을 지정하는 방식이 조금 헷갈릴 수 있습니다. axis 키워드는 결과로 나올 차원이 아니라, 축소(collapse)할 차원을 지정하는 것이라 이해하면 쉽습니다. 즉, axis=0을 지정하면 0번 축(행)을 따라 값을 합치겠다는 의미이므로, 각 열 단위로 집계가 일어납니다.
기타 집계 함수
NumPy는 이와 비슷한 방식으로 사용할 수 있는 수많은 집계 함수를 제공합니다. 또한 데이터에 결측값(NaN)이 포함되어 있을 때 이를 무시하고 계산해 주는 ‘NaN-safe’ 버전의 함수들도 함께 제공합니다(결측값 처리 섹션 참조).
다음 표는 자주 쓰이는 NumPy 집계 함수들을 정리한 것입니다.
| 함수 이름 | NaN-safe 버전 | 설명 |
|---|---|---|
np.sum |
np.nansum |
요소들의 합계 계산 |
np.prod |
np.nanprod |
요소들의 곱 계산 |
np.mean |
np.nanmean |
요소들의 평균 계산 |
np.std |
np.nanstd |
표준편차 계산 |
np.var |
np.nanvar |
분산 계산 |
np.min |
np.nanmin |
최소값 찾기 |
np.max |
np.nanmax |
최대값 찾기 |
np.argmin |
np.nanargmin |
최소값의 인덱스 찾기 |
np.argmax |
np.nanargmax |
최대값의 인덱스 찾기 |
np.median |
np.nanmedian |
요소들의 중앙값 계산 |
np.percentile |
np.nanpercentile |
요소들의 백분위수(순위 기반 통계) 계산 |
np.any |
해당 없음 | 요소 중 하나라도 참인지 확인 |
np.all |
해당 없음 | 모든 요소가 참인지 확인 |
이 함수들은 앞으로 이 책의 예제들에서 매우 자주 등장할 것입니다.
예시: 미국 대통령들의 평균 키는 얼마일까요?
NumPy 집계 함수를 사용해 실제 데이터를 요약해 보겠습니다. 역대 미국 대통령들의 키 데이터를 예로 들어보죠. 이 데이터는 data/president_heights.csv 파일에 이름과 키가 쉼표로 구분되어 저장되어 있습니다.
!head -4 data/president_heights.csv3부에서 자세히 다룰 Pandas 패키지를 사용해 파일을 읽고 키 정보를 추출해 보겠습니다(단위는 cm입니다).
import pandas as pd
data = pd.read_csv("data/president_heights.csv")
heights = np.array(data["height(cm)"])
print(heights)추출한 데이터를 바탕으로 다양한 요약 통계량을 계산해 보죠.
print("Mean height: ", heights.mean())
print("Standard deviation:", heights.std())
print("Minimum height: ", heights.min())
print("Maximum height: ", heights.max())위와 같이 집계 함수는 배열 전체를 하나의 대표값으로 요약하여 데이터의 전반적인 특징을 보여줍니다. 분위수를 계산해 데이터의 분포를 더 자세히 살펴볼 수도 있습니다.
print("25th percentile: ", np.percentile(heights, 25))
print("Median: ", np.median(heights))
print("75th percentile: ", np.percentile(heights, 75))데이터를 보니 미국 대통령들의 평균 키는 약 182cm로, 6피트가 조금 안 되는 수준임을 알 수 있습니다.
수치만 보는 것보다 Matplotlib 같은 도구를 사용해 시각화하면 데이터의 흐름을 훨씬 더 쉽게 파악할 수 있습니다(Matplotlib은 4부에서 자세히 다룹니다). 아래 코드를 실행해 히스토그램을 그려보겠습니다.
%matplotlib inline
import matplotlib.pyplot as plt
plt.style.use("seaborn-whitegrid")plt.hist(heights)
plt.title("Height Distribution of US Presidents")
plt.xlabel("height (cm)")
plt.ylabel("number");