청크 간 점진적 집계
전체 파일을 메모리에 저장하지 않고 청크 간 누적 개수, 합계, 최솟값·최댓값을 계산합니다.
청크 간 점진적 집계은(는) CoddyKit의 무료 Pandas & NumPy Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Pandas & NumPy Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Pandas & NumPy Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
점진적 집계가 필요한 이유
점진적 집계는 여러 컴퓨터에 계산을 분산하지 않고도 RAM보다 큰 데이터 세트를 분석하는 핵심 방법입니다. 최종 통계를 계산하기 위해 모든 데이터를 로드하는 대신 누적 변수인 부분 합계, 개수, 최솟값/최댓값을 유지하고 각 청크마다 업데이트합니다. 전체 파일을 검사한 후 이러한 가벼운 누적 변수에서 최종 결과를 구성합니다. 이 패턴을 사용하면 단일 노트북에서도 테라바이트 크기의 파일로 확장할 수 있습니다.
행 개수 세기 및 평균 계산하기
청크 전체의 mean을 계산하려면 누적 합계와 개수를 별도로 추적해야 합니다. 청크의 크기가 서로 다를 수 있으므로 청크별 평균을 단순히 평균 내서는 안 됩니다. 올바른 공식은 total_sum / total_count입니다. 이 패턴은 분산, 상관관계, 히스토그램처럼 분해 가능한 모든 값으로 확장할 수 있으며, 이러한 값에는 모두 점진적 계산 공식이 있습니다.
import pandas as pd
total_sum = 0.0
total_count = 0
for chunk in pd.read_csv('transactions.csv', chunksize=100000):
total_sum += chunk['amount'].sum()
total_count += chunk['amount'].notna().sum()
grand_mean = total_sum / total_count
print(f'Rows processed: {total_count:,}')
print(f'Grand mean: {grand_mean:.4f}')점진적으로 최솟값과 최댓값 계산하기
청크 전체의 전역 최솟값과 최댓값을 추적하는 방법은 간단합니다. 파이썬의 float('inf')와 float('-inf')로 초기화한 다음 각 청크의 최솟값/최댓값으로 업데이트하십시오. 이렇게 하면 중간 데이터를 저장할 필요가 없습니다. 그룹 식별자를 키로 하는 사전을 유지하면 그룹별 최솟값/최댓값에도 이 패턴을 일반화할 수 있습니다.
import pandas as pd
global_min = float('inf')
global_max = float('-inf')
for chunk in pd.read_csv('prices.csv', chunksize=50000):
chunk_min = chunk['price'].min()
chunk_max = chunk['price'].max()
if chunk_min < global_min:
global_min = chunk_min
if chunk_max > global_max:
global_max = chunk_max
print(f'Price range: {global_min} to {global_max}')점진적으로 빈도 세기
범주형 열의 경우, 각 청크의 value_counts() 결과를 Pandas Series 누적 변수에 더하여 누적 빈도 사전을 유지하십시오. Pandas Series의 덧셈은 인덱스 레이블을 기준으로 정렬되므로 이후 청크에 새로 나타난 범주도 자동으로 포함됩니다. 모든 청크를 처리한 후 개수순으로 정렬하면 전체 데이터 세트에서 빈도가 높은 범주를 확인할 수 있습니다.
import pandas as pd
freq = pd.Series(dtype='int64')
for chunk in pd.read_csv('orders.csv',
chunksize=100000,
usecols=['category']):
chunk_counts = chunk['category'].value_counts()
freq = freq.add(chunk_counts, fill_value=0)
# Final sorted frequency table
print(freq.sort_values(ascending=False).head(10))점진적으로 GroupBy 집계하기
청크 전체에서 groupby 합계 또는 개수를 계산하려면 각 청크 안에서 groupby().agg()를 적용하고 결과 Series 또는 DataFrame을 저장하십시오. 루프가 끝나면 모든 부분 결과를 연결하고 두 번째 groupby를 적용하여 결합합니다. 데이터가 그룹별이 아니라 날짜순으로 정렬되어 있을 때처럼 여러 청크에 같은 그룹이 나타나는 경우에도 이 2단계 방식으로 올바르게 처리할 수 있습니다.
import pandas as pd
partials = []
for chunk in pd.read_csv('sales.csv',
chunksize=100000,
usecols=['region', 'product', 'revenue']):
p = chunk.groupby(['region', 'product'])['revenue'].sum()
partials.append(p)
final = (
pd.concat(partials)
.groupby(level=['region', 'product'])
.sum()
.sort_values(ascending=False)
)
print(final.head(10))분산을 점진적으로 계산하기(Welford 방법)
청크 전체의 분산을 계산하는 일은 평균보다 어렵습니다. 단순한 공식 E[X²] - E[X]²은 평균이 큰 경우 치명적인 상쇄 오차가 발생합니다. Welford 온라인 알고리즘은 누적 평균과 편차 제곱합을 유지하며, 새 값이 들어올 때마다 수치적으로 안정적인 방식으로 업데이트합니다. SciPy가 이를 구현하고 있지만, 이 패턴을 이해하면 가중 분산과 공분산으로 확장할 수 있습니다.
import pandas as pd
import numpy as np
# Simple two-pass approach using stored chunk stats
chunk_stats = []
for chunk in pd.read_csv('data.csv',
chunksize=100000,
usecols=['value']):
n = chunk['value'].count()
mean = chunk['value'].mean()
var = chunk['value'].var(ddof=1)
chunk_stats.append((n, mean, var))
# Combine: use pooled variance formula
total_n = sum(s[0] for s in chunk_stats)
total_mean = sum(s[0]*s[1] for s in chunk_stats) / total_n
pooled_var = sum((s[0]-1)*s[2] + s[0]*(s[1]-total_mean)**2
for s in chunk_stats) / (total_n - 1)
print(f'Grand variance: {pooled_var:.4f}')점진적 히스토그램 만들기
RAM보다 큰 파일 전체에서 열의 분포를 계산하려면 점진적 히스토그램이 필요합니다. 먼저 작은 표본이나 도메인 지식을 바탕으로 구간 경계를 정한 다음, 각 청크 안에서 np.histogram(chunk_values, bins=edges)를 사용하여 개수를 누적하십시오. 마지막에는 결합된 개수를 막대 차트로 표시합니다. Kafka Streams와 Flink 같은 스트리밍 시스템이 근사 히스토그램을 계산하는 방식도 이와 같습니다.
import pandas as pd
import numpy as np
# Decide bin edges from a sample
sample = pd.read_csv('amounts.csv', nrows=5000)
bins = np.linspace(sample['amount'].min(),
sample['amount'].max(), 21)
counts = np.zeros(len(bins) - 1, dtype='int64')
for chunk in pd.read_csv('amounts.csv',
chunksize=100000,
usecols=['amount']):
chunk_counts, _ = np.histogram(
chunk['amount'].dropna(), bins=bins
)
counts += chunk_counts
print('Histogram counts:', counts[:5], '...')고유값을 근사적으로 추적하기
청크 전체에서 정확한 고유값 개수를 세려면 모든 고유값을 저장해야 하며, 그 수가 수백만 개에 이를 수도 있습니다. 대규모 데이터에서 근사적인 개수를 구하려면 파이썬의 hyperloglog 라이브러리로 사용할 수 있는 HyperLogLog 스케치를 사용하십시오. 또는 청크별 고유값을 집합으로 추적한 뒤 합집합을 구할 수도 있지만, 집합의 크기가 계속 제한 없이 커집니다. 간단한 근사치가 필요하다면 청크마다 pd.Series.nunique()를 사용하고 평균을 보고하십시오. 정확하지는 않지만 데이터 프로파일링에는 충분한 경우가 많습니다.
import pandas as pd
unique_ids = set()
for chunk in pd.read_csv('events.csv',
chunksize=100000,
usecols=['user_id']):
unique_ids.update(chunk['user_id'].dropna().unique())
print(f'Distinct user IDs: {len(unique_ids):,}')
# Warning: the set may grow large for high-cardinality columns장시간 실행 중 진행 상황 보고하기
수 기가바이트의 파일을 처리하는 데는 몇 분이 걸릴 수 있습니다. 파이프라인이 실행 중인지 확인하고 남은 시간을 추정할 수 있도록 진행 상황 보고를 추가하십시오. 처리한 바이트 수나 행 수를 세고 파일 크기와 비교하십시오. tqdm 라이브러리의 tqdm(reader) 래퍼를 사용하면 이 작업을 간단히 수행할 수 있습니다. tqdm이 없더라도 10개 청크마다 상태 줄을 출력하면 장시간 일괄 작업 중에 유용한 피드백을 얻을 수 있습니다.
import pandas as pd
import time
chunksize = 100000
start = time.time()
rows_processed = 0
for i, chunk in enumerate(pd.read_csv('big.csv',
chunksize=chunksize)):
rows_processed += len(chunk)
# Report every 10 chunks
if (i + 1) % 10 == 0:
elapsed = time.time() - start
rate = rows_processed / elapsed
print(f'Chunk {i+1}: {rows_processed:,} rows '
f'@ {rate/1000:.0f}k rows/sec')
print(f'Total: {rows_processed:,} rows in {time.time()-start:.1f}s')집계 전에 필터링하기
불필요한 데이터를 누적하지 않도록 각 청크 안에서 집계하기 전에 필터를 적용하십시오. 예를 들어 2024년 주문만 관심이 있다면 groupby를 수행하기 전에 청크의 날짜 열을 필터링하십시오. 이렇게 하면 부분 결과에 필요한 메모리가 줄어들고 최종 연결 단계도 빨라집니다. 효율적인 데이터 처리의 기본 원칙에 따라 파이프라인에서 필터는 항상 가능한 한 이른 단계에 적용하십시오.
import pandas as pd
partials = []
for chunk in pd.read_csv('orders.csv',
chunksize=100000,
parse_dates=['order_date']):
# Filter early: only 2024 orders
mask = chunk['order_date'].dt.year == 2024
filtered = chunk.loc[mask, ['category', 'revenue']]
if len(filtered) > 0:
p = filtered.groupby('category')['revenue'].sum()
partials.append(p)
if partials:
result = pd.concat(partials).groupby(level=0).sum()
print(result)중간 결과 저장하기
매우 오래 실행되는 작업의 경우 중간 결과를 주기적으로 저장하여 프로세스가 중단되더라도 체크포인트에서 재개할 수 있도록 하십시오. N개의 청크를 처리할 때마다 청크별 집계 결과를 Parquet 또는 CSV 파일에 기록하십시오. 1000개 중 800번째 청크에서 작업이 실패하더라도 저장된 집계 결과를 다시 불러와 전체 파일을 재처리하는 대신 중단된 지점부터 계속할 수 있습니다. 이러한 복원력 패턴은 운영 환경의 데이터 파이프라인에 필수적입니다.
import pandas as pd
import os
CHECKPOINT = 'checkpoint.csv'
running_total = 0.0
running_count = 0
# Resume from checkpoint if it exists
if os.path.exists(CHECKPOINT):
ckpt = pd.read_csv(CHECKPOINT)
running_total = ckpt['total'].iloc[0]
running_count = int(ckpt['count'].iloc[0])
print(f'Resuming from checkpoint: {running_count:,} rows')
for chunk in pd.read_csv('huge.csv', chunksize=100000):
running_total += chunk['value'].sum()
running_count += len(chunk)
# Save checkpoint
pd.DataFrame({'total': [running_total],
'count': [running_count]}).to_csv(CHECKPOINT, index=False)
print(f'Final mean: {running_total / running_count:.4f}')빠른 확인
이 강의에서 다룬 데이터 분석 개념을 얼마나 이해했는지 확인해 보십시오.
강의 요약
이 강의에서는 다음을 배웠습니다. 실행 중 누적기(sum, count, min/max, 빈도 Series)를 사용하면 대용량 파일 전체를 일정한 메모리 사용량으로 집계할 수 있고, 2단계 groupby(청크별 부분 groupby 수행 후 연결하고 다시 그룹화)를 사용하면 여러 청크에 걸친 그룹을 올바르게 처리할 수 있으며, 각 청크 내에서 조기에 필터링하면 누적 단계의 비용을 줄일 수 있습니다. 다음 강의에서는 대규모 데이터셋에서 Pandas를 손쉽게 대체하여 병렬 처리할 수 있는 Dask DataFrames를 살펴보겠습니다.
자주 묻는 질문
“청크 간 점진적 집계” 강의는 무료인가요?
네 — “청크 간 점진적 집계” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Pandas & NumPy Academy 강의 전체를 잠금 해제할 수 있습니다. Pandas & NumPy Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“청크 간 점진적 집계”에서 뭘 배우나요?
전체 파일을 메모리에 저장하지 않고 청크 간 누적 개수, 합계, 최솟값·최댓값을 계산합니다. 브라우저에서 직접 실행하는 실습 코드로 Pandas & NumPy Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Pandas & NumPy Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Pandas & NumPy Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.
“청크 간 점진적 집계” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Pandas & NumPy Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Pandas & NumPy Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.