본문 바로가기

Programming/Tip&Informaion

[DataScience] pandas의 대안은? modin, dask, vaex 비교하기

데이터 사이언스를 시작할 때 주로 사용하는 언어는 R과 Python이 있습니다.

보통 개발을 시작하신 분들은 python으로 주로 입문하게 되죠. 이 때 주로 사용하는 라이브러리는 Pandas 라는 라이브러리입니다.

pandas 는 여러 파일을 파싱하는 것부터 전체 데이터 테이블을 NumPy 형태의 행렬 배열로 변환하는 다양하게 이용가능 합니다. 이런 기능들이 pandas가 데이터 사이언스와 머신러닝에서 잘 사용되는 이유입니다.

 

이런 pandas에게도 단점이 있으니 데이터가 많아질 수록 사용하는 메모리가 늘어나고 속도가 느려진다는 것입니다.

물론 pandas에서 천만 row도 처리 가능할 수 있지만, 그 경우에 10기가의 메모리가 필요합니다. 또한 pandas는 싱글코어로만 작동하고 ram의 범위 안에서만 작동합니다.

 

이런 단점들을 해소하기 위해 다양한 라이브러리들이 있습니다.

그 중에 modin, dask, vaex 가 있습니다.

간략히 살펴보면 다음과 같습니다.

 

1. dask

    1) 기본적으로 pandas보다는 느리지만 큰 데이터에도 잘 작동한다.

    2) 여러개의 머신이나 하나의 머신에서 여러개의 코어를 작동하기에 좋다.

    3) 메모리를 초과하는 데이터도 다룰 수 있다.

 

2. modin

    1) pandas의 함수와 fallback을 재구현한 DataFrame을 위한 새로운 'algebra' 입니다. (단순히 Pandas 만을 위한 게 아님)

    2) 어떤 코드 수정도 없이 행과 열을 자동으로 병렬로 사용한다.

    3) 내부적으로 Ray 나 dask 를 사용합니다.

         -> dask 등이 pandas를 대체하기 위한 framework 라면 modin은 그런 dask를 pandas 문법처럼 사용하게 해주는 api 와 유사합니다.

 

3. vaex

    1) pandas와 상관없는 pandas와 유사한 새로운 프로젝트

    2) 램에 효율적인 새로운 string 타입을 갖고 있어 string 타입을 다룰 때 좋다.

    3) 메모리 매핑 lazy computation

    4) 수억개의 데이터를 랩탑에서 사용 가능

 

4.요약 결론

    1) modin은 in-ram dataset 에서 코드 수정없이 더 빠른 속도를 원할 때 사용

    2) dask는 메모리보다 더 큰 데이터셋을 사용할 때 사용

    3) vaex는 memory mapped (HDF5) datasets이나 string 처리가 많을 때 사용

 

으로 요약할 수 있겠습니다.


간단한 실습을 통해 좀 더 비교를 해봅시다.

우선 라이브러리를 설치합니다.

 

pip install vaex
pip install modin
pip install dask
pip install modin[dask]
pip install dask[dataframe]

* modin[dask] 의 경우 아직 정식은 아니지만 사용하였습니다.

 

jupyter notebook에선 앞에 !를 붙이고 실행시키면 되겠습니다.

 

import pandas as pd
import modin.pandas as mp              #modin 예제에선 mp가 아닌 pandas와 같은 pd 를 사용합니다.
import dask.dataframe as dd
import vaex
import numpy as np

 

실제 문법 및 성능을 비교해보겠습니다.

시간 측정은 %time을 사용하였습니다.

* 제 환경은 노트북 환경으로 GPU가 없습니다.

* 데이터의 크기는 약 2GB를 조금 넘습니다.

 

%time pandas_df = pd.read_csv('data.csv')
%time dask_df = dd.read_csv('data.csv')
%time modin_df = mp.read_csv('data.csv')
%time vaex_df = vaex.from_csv('data.csv')

pandas: CPU times: user 15.4 s,    sys: 2.34 s,    total: 17.8 s     Wall time: 17.7 s

dask:     CPU times: user 10.2 ms, sys: 3.39 ms, total: 13.6 ms  Wall time: 10.2 ms

modin:  CPU times: user 2.64 s,    sys: 1.43 s,     total: 4.07 s    Wall time: 11 s

vaex:     CPU times: user 27.8 s,     sys: 3.02 s,    total: 30.8 s    Wall time: 31.8 s

 

일단 dask의 비교 불가한 속도네요.. modin은 의미있는 속도를 냈습니다. vaex는 많이 느렸습니다.

그리고 눈여겨볼 점은 vaex의 경우 문법이 많이 다르다는 걸 알 수 있습니다.

속도: dask > modin > pandas > vaex

 

재밌는 점은 dask의 비교불가능한 속도는 lazy compute의 영향으로 실제로 계산을 하지 않았다는 점입니다.

*lazy compute란 실제로 값이 사용될 때까진 연산을 하지 않고 미루다 정말로 값이 필요할 때 계산을 하여 불필요한 연산 시간을 줄이는 것입니다.

 

 

 

 

그래서 단순히 dask_df 를 출력하면 데이터의 값을 보여주지 않고 dask_df.head()를 하면 값이 보입니다.

시간의 차이도 다른 라이브러리들은 head 출력 시 최대 6ms인 것에 비교하면 41.7ms 로 많이 차이가 납니다. (wall time은 더 심합니다.)

* pandas: 0.9ms, modin: 6ms, vaex: 1.9ms

 

이번엔 groupby 연산을 비교하겠습니다.

%time pandas_df.groupby(['column1','column2','column3']).sum()
%time dask_df.groupby(['column1','column2','column3']).sum()
%time modin_df.groupby(['column1']).sum()
%time vaex_df.groupby(by=['column1','column2','column3'],agg={'column4': vaex.agg.sum('column4'),'column5': vaex.agg.sum('column5'),'column6': vaex.agg.sum('column6'),'column7': vaex.agg.sum('column7'),'column8': vaex.agg.sum('column8')})

pandas: CPU times: user 2.84 s,   sys: 1.33 s,   total: 4.17 s     Wall time: 4.01 s

dask:     CPU times: user 21.8 ms, sys: 261 µs,  total: 22.1 ms Wall time: 19.7 ms

modin:  CPU times: user 857 ms,  sys: 536 ms, total: 1.39 s    Wall time: 3.68 s

vaex:     CPU times: user 6.93 s,    sys: 3.09 ms, total: 6.94 s    Wall time: 1.13 s

 

*modin의 경우 여러행 groupby는 베타 버전으로 에러가 발생하여 단일행 groupby를 진행했습니다.

*vaex의 경우 다른 라이브러리와 달리 일일이 값을 할당해줬습니다.

 

이 때 dask는 또 결과값을 보여주지 않습니다.

결과값을 보고 싶다면 뒤에 .compute()를 붙여주면 계산을 합니다.

 

%time dask_df.groupby(['REG_YYMM','CARD_SIDO_NM','STD_CLSS_NM']).sum().compute()

CPU times: user 683 ms, sys: 181 ms, total: 864 ms Wall time: 6.2 s

 

modin의 경우 직접 비교가 불가능하지만 대략 2.5배 정도 추가로 가정하겠습니다.

 

cpu time: dask < pandas < modin < vaex

wall time: dask < vaex < pandas < dask(compute) < modin

 

* 실험 결과

매우 의미있는 결과를 내진 못 했지만, 나름 정리해보겠습니다.

1. 파일을 읽는 데는 대부분의 라이브러리가 pandas 보다 효율적입니다.

2. vaex의 경우 문법이 다른 것 뿐만 아니라 예시 수준의 데이터에 대해선 크게 효과를 보지 못 했습니다.

    (string에 대한 실험도 필요해보입니다.)

3. dask의 경우 lazy compute를 활용하기 때문에 필요할 때만 연산을 사용하여 잘 사용하면

    효율적으로 쓸 수 있을 것이란 걸 보여줍니다.

4. modin의 경우 불안정한(?) dask 버전을 사용해서 그런 지는 모르겠지만, groupby에서 아쉬운 모습을 보여줬습니다.

    groupby와 같은 문제들이 해결된다면 다시 비교를 해봐야 정확할 것 같습니다.

 

시간이 된다면 다음에 좀 더 의미있는 비교를 해봐야 할 것 같습니다...

 

 

참고

speakerdeck.com/ianozsvald/flying-pandas-modin-dask-and-vaex

ianozsvald.com/2020/04/27/flying-pandas-and-making-pandas-fly-virtual-talks-this-weekend-on-faster-data-processing-with-pandas-modin-dask-and-vaex/