0%

1. Polars란

오픈소스 프로젝트인 Polars에서 기여하는 과정을 정리합니다.

Polar란

polarsApache Arrow Columnar Format 메모리 모델을 바탕으로 개발된 DataFrames 라이브러리이며, Rust로 작성되었다. 데이터 분석 시에 사용되는 pandas 라이브러리와 많이 비교된다.

Polars 장점

  • 매우 빠르다. 다른 라이브러리와의 벤치마킹 결과를 이 페이지에서 확인할 수 있다.
  • 가볍다. Dependency가 거의 없고 Import 속도도 매우 빠르다.
  • RAM보다 큰 데이터도 핸들링할 수 있다. 메모리보다 큰 데이터가 있는 경우 쿼리를 스트리밍 방식으로 처리하여 메모리 요구량이 줄어든다.

사용 방법 예시

자세한 사용 방법은 유저 가이드 에서 확인할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
>>> import polars as pl

# 데이터프레임 생성
>>> df = pl.DataFrame(
... {
... "A": [1, 2, 3, 4, 5],
... "fruits": ["banana", "banana", "apple", "apple", "banana"],
... "B": [5, 4, 3, 2, 1],
... "cars": ["beetle", "audi", "beetle", "beetle", "beetle"],
... }
... )

>>> df
shape: (5, 4)
┌─────┬────────┬─────┬────────┐
│ A ┆ fruits ┆ B ┆ cars │
│ --- ┆ --- ┆ --- ┆ --- │
│ i64 ┆ str ┆ i64 ┆ str │
╞═════╪════════╪═════╪════════╡
1 ┆ banana ┆ 5 ┆ beetle │
2 ┆ banana ┆ 4 ┆ audi │
3 ┆ apple ┆ 3 ┆ beetle │
4 ┆ apple ┆ 2 ┆ beetle │
5 ┆ banana ┆ 1 ┆ beetle │
└─────┴────────┴─────┴────────┘

# "fruits"기준으로 정렬
>>> df.sort("fruits").select(
... "fruits", # "fruits" 컬럼
... "cars", # "cars" 컬럼
... pl.lit("fruits").alias("literal_string_fruits"),
... pl.col("B").filter(pl.col("cars") == "beetle").sum(),
... pl.col("A").filter(pl.col("B") > 2).sum().over("cars").alias("sum_A_by_cars"),
... pl.col("A").sum().over("fruits").alias("sum_A_by_fruits"),
... pl.col("A").reverse().over("fruits").alias("rev_A_by_fruits"),
... pl.col("A").sort_by("B").over("fruits").alias("sort_A_by_B_by_fruits"),
... )
shape: (5, 8)
┌──────────┬──────────┬──────────────┬─────┬─────────────┬─────────────┬─────────────┬─────────────┐
│ fruits ┆ cars ┆ literal_stri ┆ B ┆ sum_A_by_ca ┆ sum_A_by_fr ┆ rev_A_by_fr ┆ sort_A_by_B │
│ --- ┆ --- ┆ ng_fruits ┆ --- ┆ rs ┆ uits ┆ uits ┆ _by_fruits │
│ str ┆ str ┆ --- ┆ i64 ┆ --- ┆ --- ┆ --- ┆ --- │
│ ┆ ┆ str ┆ ┆ i64 ┆ i64 ┆ i64 ┆ i64 │
╞══════════╪══════════╪══════════════╪═════╪═════════════╪═════════════╪═════════════╪═════════════╡
"apple""beetle""fruits"114744
"apple""beetle""fruits"114733
"banana""beetle""fruits"114855
"banana""audi""fruits"112822
"banana""beetle""fruits"114811
└──────────┴──────────┴──────────────┴─────┴─────────────┴─────────────┴─────────────┴─────────────┘

위 예시 중에서 몇 가지 문법을 간단하게 해석해보자.

  • pl.lit("fruits").alias("literal_string_fruits"): fruits라는 문자열을 데이터로 literal_string_fruits 컬럼 생성
  • pl.col("B").filter(pl.col("cars") == "beetle").sum(): cars 컬럼이 beetle인 B 요소만 더한 값
  • pl.col("A").filter(pl.col("B") > 2).sum().over("cars").alias("sum_A_by_cars"): B 컬럼 값이 2보다 큰 A 컬럼을 cars 기준으로 더한 값
  • pl.col("A").sum().over("fruits").alias("sum_A_by_fruits"): A 컬럼을 fruits 기준으로 더한 값
  • pl.col("A").reverse().over("fruits").alias("rev_A_by_fruits"): fruits 기준으로 A 컬럼 값을 반전
  • pl.col("A").sort_by("B").over("fruits").alias("sort_A_by_B_by_fruits"): fruits 기준으로 A 컬럼을 B 값으로 정렬

컨트리뷰션 가이드

오픈소스에 기여하기 위해서는 컨트리뷰션 가이드를 먼저 읽어보는 것이 좋다. 만약 다른 컨트리뷰터와 소통하고 싶다면 디스코드에서 만날 수 있다.

1. 해결하고 싶은 이슈 고르기

먼저 해결하고 싶은 이슈를 골라야 한다. open된 이슈 목록은 이슈 페이지에서 확인할 수 있으며, 처음 도전하는 경우 label에서 good first issue로 필터링해서 골라도 된다.

issue

만약 좀 더 주요한 이슈를 고르고 싶다면 label에서 help wanted로 필터링하면 목록을 볼 수 있다.

2. 로컬 환경 구성하기

polars는 크게 Rust, Python, Node.js로 구성되어 있다. polars의 경우 Rust와 Python 환경이 필요하며, Node.js에 기여를 하고 싶다면 nodejs-polars]를 살펴보자. 이 글에서는 polars 저장소를 기준으로 한다.

개발을 위한 로컬 환경을 구성해야 한다. 먼저 polars repo를 내 계정으로 fork 한다.

1
2
git clone git@github.com:<username>/polars.git
cd polars

그 다음 Rust와 python을 설치한다. Rust의 경우 rustup을 사용하여 다운로드 받기를 추천한다. 설치가 끝났다면 아래 명령어를 입력하여 toolchain도 설치한다.

1
rustup toolchain install nightly --component miri

마지막으로 python은 pyenv 환경을 구성한다.

1
2
3
cd py-polars
source .venv/bin/activate
make test

테스트가 정상적으로 완료되었다면 아래 코드를 사용하여 린트 도구도 정상 작동하는지 확인한다.

1
make pre-commit

모든 것이 완료되었다면 커밋할 준비가 된 것이다.

3. 이슈 해결하기

로컬 레파지토리에서 새로운 브랜치를 하나 생성해서 코딩을 시작한다.
코어 코드들은 polars 디렉토리에 있고, Python 코드들은 py-polars 디렉토리에 있다. 두 디렉토리에 모두 유용한 명령어가 포함된 Makefile이 포함되어 있다.

  • make test: 다양한 테스트를 실행.
  • make pre-commit: 포메팅과 린트 이슈를 확인.

이슈 해결을 진행할 때 아래 사항들을 유의해야 한다.

  • 위 두 개의 make 명령어가 실패하면 작업한 내용을 병합할 수 없다.
  • 테스트가 필요한 코드를 추가했다면 꼭 테스트도 추가해주어야 한다.
  • Public API를 변경하는 경우 문서를 업데이트 해야 한다.

4. PR 올리기

문제를 해결했다면 PR(Pull Request)을 올릴 수 있다. PR은 아래 가이드라인을 준수해야 한다.

  • PR 제목은 커밋 컨벤션에 맞춰 작성해야 한다. 올바르게 작성된 제목은 변경이력에 기여내용을 남기는 데 도움이 된다. 범위는 기여도에 따라 Rust 또는 Python이 될 수 있다.
  • 제목에 변경에 대한 설명을 포함해야 한다. 이 텍스트는 변령이력에 포함된다.
  • PR 설명에 작업 중인 이슈에 대한 링크를 추가해야 한다.
  • 설명에 메인테이너가 코드를 검토하는 데 도움이 될 수 있는 관련 정보를 추가해야 한다.
  • 지금 브랜치가 최신 버전에 대해 rebase가 되어 있는지 확인해야 한다.
  • 모든 Github 작업 확인을 통과했는지 확인해야 한다.

PR을 열면 메인테이너가 이를 검토하고 몇 가지 의견을 남길 수 있다. 모든 문제가 해결되면 메인테이너가 PR을 병합하고 기여한 내용이 다음 polars 릴리즈에 포함될 것이다.

해결이 막히거나 확실하지 않은 경우 PR 드래프트를 열어 도움을 요청할 수도 있다.