brunch

You can make anything
by writing

C.S.Lewis

by 유윤식 Jun 18. 2024

Polars #08

#Struct #구조체 #vs.Pandas

간단한 DataFrame 을 만들고 그 안에서

기존 컬럼들을 조합해서 Dict 타입의 새로운 컬럼을 생성해보자.


- struct 키워드를 알아야 한다.

- with_columns 함수를 사용한다.

- pandas 문법과 성능을 비교한다.


아래와 같은 데이터셋을 생성한다.


%%time

import polars as pl


pl.Config(fmt_table_cell_list_len=10)


gt = 1000000

df = pl.DataFrame({

    'A': [i for i in range(gt)],

    'B': [str(i)+'_STR' for i in range(gt)],

    'C': [bool(i) for i in range(gt)],

    'D': [i * 10 for i in range(gt)]

})



이제 A, B, C 를 사용해서 Dict 형태의 구조체를 만들어 보자.



%%time

df = df.with_columns([

    pl.struct(['A', 'B', 'C']).alias('abc_struct'),

    pl.struct(['B', 'C', 'D']).alias('bcd_struct')

])


df


어렵지 않게 구조체 데이터를 생성할 수 있다.


여기서,

abc_struct 의 값에 접근해서 값을 변경 할 수 있을까?

아직 그런 함수는 찾지 못했다.


하지만!

다른 방식으로 접근한다면 가능하다.


변경하고자 하는 key 값의 데이터를 변경하고 새로운 컬럼으로 추가한다.

그리고 다시 다른 값들과 조합해서 struct 를 생성한다.



%%time


df = df.with_columns([

    (pl.col('abc_struct').struct.field('A') ** 2).alias('tmp_modified_a_field')

]).with_columns([

    pl.struct(['tmp_modified_a_field', 'B', 'C']).alias('abc_struct')

]).drop(['tmp_modified_a_field'])



이걸 pandas 에서 돌려보았는데

시간이 너무 오래 걸려서 그만 두었다.

즉, 성능 비교 자체가 어렵다!


polars 에서도 apply, lambda, map 등을 사용하면 pandas 처럼 느려진다.

최대한 functional API 를 잘 조합해서 로직을 만드는게 최우선이다.

도저히 만들 수 없을 때

Rust 를 살짝 배워서 원하는 로직을 UDF 로 만들고

Python 에서 import 해서 polars 와 함께 사용하면 될 것이다.

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari