수백만 row가 넘는 데이터를 전처리하는데 전처리가 조금 복잡하여 iterrows를 돌렸더니 시간이 너무 오래 걸려 쓰게 된 글입니다.
다음과 같이 dataframe이 있을 때 각각의 iteration방법들을 비교해 보겠습니다.
1. for loop
%%timeit
for row in range(len(df)):
tmp = df.iloc[row,0]+df.iloc[row,1]+df.iloc[row,2]
1min 21s ± 6.04 s per loop (mean ± std. dev. of 7 runs, 1 loop each)
2. iterrows
%%timeit
for _, row in df.iterrows():
tmp = (row['A']+row['B']+row['C'])
48.1 s ± 2.11 s per loop (mean ± std. dev. of 7 runs, 1 loop each)
for loop보다 빠릅니다.
3. apply
%%timeit
df.apply(lambda row: row['A']+row['B']+row['C'],axis=1)
16.7 s ± 1.65 s per loop (mean ± std. dev. of 7 runs, 1 loop each)
iterrows보다 빠릅니다.
하지만 apply는 새로운 Series를 반환하기 때문에 dataframe의 크기가 크다면 부하가 걸릴 수 있습니다.
apply함수는 Cython으로 돌기 때문에 연산이 빠릅니다. 따라서 복잡한 전처리 함수를 따로 적용해야 한다면 apply를 사용하는 것이 좋아 보입니다.
4. itertuples
%%timeit
for row in df.itertuples():
tmp = row.A+row.B+row.C
856 ms ± 198 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
itertuples가 iterrows에 비해 매우 빨라졌습니다.
itertuples과 iterrows는 무슨 차이가 있을까요?
%%prun 매직함수를 통해 얼마나 함수가 호출됐는지 알아볼 수 있습니다.
5. iterrows vs itertuples
%%prun
for _, row in df.iterrows():
tmp = (row['A']+row['B']+row['C'])
167000023 function calls (165000023 primitive calls) in 104.695 seconds
%%prun
for row in df.itertuples():
tmp = row.A+row.B+row.C
4000578 function calls (4000570 primitive calls) in 1.431 seconds
호출 함수 개수에서 차이가 많이 납니다. 이 때문에 itertuples가 매우 빠를 수 있습니다.
5. numpy
%%timeit
for row in df.values:
tmp = row[0] +row[1]+row[2]
963 ms ± 140 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
values도 속도가 빠르지만 column을 지정하여 부르기 불편한 점이 있습니다.
'Python' 카테고리의 다른 글
[Python] Folium으로 지도에 행정구역 경계 표시하기 (0) | 2023.02.26 |
---|---|
[Python] selenium 사용 시 chromedriver 자동 업데이트하기 (0) | 2023.02.12 |
[Python] Faiss, 효율적인 유사도 검색 엔진 (1) | 2022.09.30 |
[Python] 페이지랭크 알고리즘 (0) | 2022.08.14 |
디렉토리에서 파일리스트 가져오기 (glob, os.walk) (0) | 2022.04.10 |