본문으로 건너뛰기
김신건의 로그

[Pandas] iterrows / itertuples

· 수정 · 📖 약 1분 · 289자/단어 #python #pandas #iteration
Pandas iterrows, Pandas itertuples, pandas 행 순회

정의

  • iterrows() : (index, Series) 순회
  • itertuples() : NamedTuple 순회 (빠름, 권장)
  • items() : (column_name, Series) 순회

기본

for idx, row in df.iterrows():
    print(idx, row['name'], row['age'])

for row in df.itertuples():
    print(row.Index, row.name, row.age)

성능 비교 (강한 권고: 가능하면 벡터 연산)

python
import pandas as pd
import time
df = pd.DataFrame({'a': range(100_000), 'b': range(100_000)})

t = time.time(); total = 0
for _, r in df.iterrows(): total += r['a'] + r['b']
print(f'iterrows:   {time.time()-t:.2f}s')

t = time.time(); total = 0
for r in df.itertuples(): total += r.a + r.b
print(f'itertuples: {time.time()-t:.2f}s')

t = time.time()
total = (df['a'] + df['b']).sum()
print(f'vectorized: {time.time()-t:.4f}s')
결과
iterrows:   3.85s
itertuples: 0.18s
vectorized: 0.0009s

itertuplesiterrows 보다 ~20 배 빠르고, 벡터 연산은 다시 그 200 배 빠르다.

IMPORTANT

거의 모든 경우 iterrows / itertuples 를 피하라. 벡터 연산 / apply / np.where / groupby 로 같은 결과를 만들 수 있는지 먼저 검토. 정 필요하면 itertuples.

itertuples 옵션

df.itertuples()                # NamedTuple with Index
df.itertuples(index=False)     # Index 제거
df.itertuples(name='Row')      # NamedTuple 이름 지정

iterrows 의 함정

1. dtype 손실

iterrows 는 각 행을 Series 로 반환. 같은 컬럼이 다른 dtype 이면 모두 object 로 강등.

for _, r in df.iterrows():
    type(r['age'])    # 원래 int 였어도 object 일 수 있음

itertuples 는 컬럼별 dtype 보존.

2. row 수정해도 원본에 반영 안 됨

for _, r in df.iterrows():
    r['age'] = r['age'] + 1     # ❌ 원본 df 안 바뀜

3. 매우 느림

CPython 루프 + Series 생성 비용.

items, 컬럼 순회

for name, col in df.items():
    print(name, col.dtype, col.sum())

이건 보통 빠르고 의미가 명확.

진짜로 행 단위 처리가 필요할 때

  1. apply(fn, axis=1) : iterrows 보다 빠름
  2. itertuples() : 가장 빠른 Python 루프
  3. numpy / numba / cython : 더 빠르게
# apply
df['c'] = df.apply(lambda r: r['a'] + r['b'], axis=1)

# numpy 벡터화 (가장 빠름)
df['c'] = df['a'].values + df['b'].values

# 한 번의 함수가 모든 입력을 받게
@np.vectorize
def my_fn(a, b):
    return a + b
df['c'] = my_fn(df['a'], df['b'])

그래도 iterrows 가 필요한 경우

  • API 가 dict / NamedTuple 입력을 요구
  • 디버깅 / 한 번만 도는 작은 데이터
  • 외부 시스템에 한 행씩 전송

참고

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기