polarsの基本操作
polarsとは
pandasの様にデータフレーム形式でデータを扱うことができ、pandasより高速などの理由から最近話題のライブラリです。
polars
今回はAPI referenceを参考にしながら基本的な操作を試してみたいと思います。
インストール、バージョン
Excelファイルの読み書きにxlsx2csvというライブラリを使っているようだったので合わせてインストールしました。
どちらもpipでインストール可能です。
pip install polarspip install xlsx2csv
バージョンは以下の通りです。
bash
python 3.7.6
polars 0.15.16
xlsx2csv 0.8.1
ファイルIO
まずはファイルの読み書きを行ってみます。
csvファイルの読み書き
read_csv()、write_csv()という関数があるので基本的にはこれを使えばcsvの読み書きが可能です。
データフレームを生成→csvファイルへ書き込み→作成したcsvからデータを読み込み
という処理を行ってみました。
import polars as plif __name__ == '__main__':# データフレーム生成df = pl.DataFrame({'col0': [0,1,2], 'col1': [3,4,5]})print(df)# shape: (3, 2)# ┌──────┬──────┐# │ col0 ┆ col1 │# │ --- ┆ --- │# │ i64 ┆ i64 │# ╞══════╪══════╡# │ 0 ┆ 3 │# │ 1 ┆ 4 │# │ 2 ┆ 5 │# └──────┴──────┘# csvファイルへ書き込みdf.write_csv('sample.csv')# csvファイルの読み込みdf_csv = pl.read_csv('sample.csv')print(df_csv)# shape: (3, 2)# ┌──────┬──────┐# │ col0 ┆ col1 │# │ --- ┆ --- │# │ i64 ┆ i64 │# ╞══════╪══════╡# │ 0 ┆ 3 │# │ 1 ┆ 4 │# │ 2 ┆ 5 │# └──────┴──────┘
保存したデータが読み込めていることが確認できます。
Excelファイルの読み込み
Excelファイルに関しては現状read_excel()という関数しか用意されていないようなので読み込みしか行えないようです。
下記の様なデータが入ったサンプルファイルを用意して動作確認してみました。
col0_sheet1 | col1_sheet1 |
---|---|
0 | 3 |
1 | 4 |
2 | 5 |
import polars as plif __name__ == '__main__':df_xlsx = pl.read_excel('sample.xlsx', sheet_id=1)print(df_xlsx)# shape: (3, 2)# ┌─────────────┬─────────────┐# │ col0_sheet1 ┆ col1_sheet1 │# │ --- ┆ --- │# │ i64 ┆ i64 │# ╞═════════════╪═════════════╡# │ 0 ┆ 3 │# │ 1 ┆ 4 │# │ 2 ┆ 5 │# └─────────────┴─────────────┘
Excelファイルが読み込めていることがわかります。
今回は「sheet_id=1」でシート番号を指定して読み込みましたが、
「sheet_name='Sheet1'」のようにシート名を指定しても読み込み可能です。
行の抽出
ユーザーガイドと同じようにirisデータセットを使用してデータを操作してみます。
まずはデータの取得を行います。
df = pl.read_csv("https://j.mp/iriscsv")print(df)# shape: (150, 5)# ┌──────────────┬─────────────┬──────────────┬─────────────┬───────────┐# │ sepal_length ┆ sepal_width ┆ petal_length ┆ petal_width ┆ species │# │ --- ┆ --- ┆ --- ┆ --- ┆ --- │# │ f64 ┆ f64 ┆ f64 ┆ f64 ┆ str │# ╞══════════════╪═════════════╪══════════════╪═════════════╪═══════════╡# │ 5.1 ┆ 3.5 ┆ 1.4 ┆ 0.2 ┆ setosa │# │ 4.9 ┆ 3.0 ┆ 1.4 ┆ 0.2 ┆ setosa │# │ 4.7 ┆ 3.2 ┆ 1.3 ┆ 0.2 ┆ setosa │# │ 4.6 ┆ 3.1 ┆ 1.5 ┆ 0.2 ┆ setosa │# │ ... ┆ ... ┆ ... ┆ ... ┆ ... │# │ 6.3 ┆ 2.5 ┆ 5.0 ┆ 1.9 ┆ virginica │# │ 6.5 ┆ 3.0 ┆ 5.2 ┆ 2.0 ┆ virginica │# │ 6.2 ┆ 3.4 ┆ 5.4 ┆ 2.3 ┆ virginica │# │ 5.9 ┆ 3.0 ┆ 5.1 ┆ 1.8 ┆ virginica │# └──────────────┴─────────────┴──────────────┴─────────────┴───────────┘
行を指定してデータを取得することが出来ます。
# 0番目のデータを取得print(df[0])# shape: (1, 5)# ┌──────────────┬─────────────┬──────────────┬─────────────┬─────────┐# │ sepal_length ┆ sepal_width ┆ petal_length ┆ petal_width ┆ species │# │ --- ┆ --- ┆ --- ┆ --- ┆ --- │# │ f64 ┆ f64 ┆ f64 ┆ f64 ┆ str │# ╞══════════════╪═════════════╪══════════════╪═════════════╪═════════╡# │ 5.1 ┆ 3.5 ┆ 1.4 ┆ 0.2 ┆ setosa │# └──────────────┴─────────────┴──────────────┴─────────────┴─────────┘# マイナスの値も指定可能print(df[-1])# shape: (1, 5)# ┌──────────────┬─────────────┬──────────────┬─────────────┬───────────┐# │ sepal_length ┆ sepal_width ┆ petal_length ┆ petal_width ┆ species │# │ --- ┆ --- ┆ --- ┆ --- ┆ --- │# │ f64 ┆ f64 ┆ f64 ┆ f64 ┆ str │# ╞══════════════╪═════════════╪══════════════╪═════════════╪═══════════╡# │ 5.9 ┆ 3.0 ┆ 5.1 ┆ 1.8 ┆ virginica │# └──────────────┴─────────────┴──────────────┴─────────────┴───────────┘# 複数行のデータ取得print(df[0:5])# shape: (5, 5)# ┌──────────────┬─────────────┬──────────────┬─────────────┬─────────┐# │ sepal_length ┆ sepal_width ┆ petal_length ┆ petal_width ┆ species │# │ --- ┆ --- ┆ --- ┆ --- ┆ --- │# │ f64 ┆ f64 ┆ f64 ┆ f64 ┆ str │# ╞══════════════╪═════════════╪══════════════╪═════════════╪═════════╡# │ 5.1 ┆ 3.5 ┆ 1.4 ┆ 0.2 ┆ setosa │# │ 4.9 ┆ 3.0 ┆ 1.4 ┆ 0.2 ┆ setosa │# │ 4.7 ┆ 3.2 ┆ 1.3 ┆ 0.2 ┆ setosa │# │ 4.6 ┆ 3.1 ┆ 1.5 ┆ 0.2 ┆ setosa │# │ 5.0 ┆ 3.6 ┆ 1.4 ┆ 0.2 ┆ setosa │# └──────────────┴─────────────┴──────────────┴─────────────┴─────────┘
特定の条件のデータのみ抽出したい場合はfilter()関数を使用します。
ここでは「Expressions」という構造を用いてフィルタリング条件を指定しています。
「Expressions are the core strength of Polars」とあるようにpolars独自の構造となり、様々な計算処理を定義することが出来ます。
Expressions
計算用methodも多く用意されています。
expressions methods
# sepal_lengthの値が6より大きいデータのみ抽出print(df.filter(pl.col('sepal_length')>6))# shape: (61, 5)# ┌──────────────┬─────────────┬──────────────┬─────────────┬────────────┐# │ sepal_length ┆ sepal_width ┆ petal_length ┆ petal_width ┆ species │# │ --- ┆ --- ┆ --- ┆ --- ┆ --- │# │ f64 ┆ f64 ┆ f64 ┆ f64 ┆ str │# ╞══════════════╪═════════════╪══════════════╪═════════════╪════════════╡# │ 7.0 ┆ 3.2 ┆ 4.7 ┆ 1.4 ┆ versicolor │# │ 6.4 ┆ 3.2 ┆ 4.5 ┆ 1.5 ┆ versicolor │# │ 6.9 ┆ 3.1 ┆ 4.9 ┆ 1.5 ┆ versicolor │# │ 6.5 ┆ 2.8 ┆ 4.6 ┆ 1.5 ┆ versicolor │# │ ... ┆ ... ┆ ... ┆ ... ┆ ... │# │ 6.7 ┆ 3.0 ┆ 5.2 ┆ 2.3 ┆ virginica │# │ 6.3 ┆ 2.5 ┆ 5.0 ┆ 1.9 ┆ virginica │# │ 6.5 ┆ 3.0 ┆ 5.2 ┆ 2.0 ┆ virginica │# │ 6.2 ┆ 3.4 ┆ 5.4 ┆ 2.3 ┆ virginica │# └──────────────┴─────────────┴──────────────┴─────────────┴────────────┘# sepal_lengthの値が6より大きい、かつpetal_lengthの値が6より大きいデータのみ抽出print(df.filter((pl.col('sepal_length')>6) & (pl.col('petal_length')>6)))# shape: (9, 5)# ┌──────────────┬─────────────┬──────────────┬─────────────┬───────────┐# │ sepal_length ┆ sepal_width ┆ petal_length ┆ petal_width ┆ species │# │ --- ┆ --- ┆ --- ┆ --- ┆ --- │# │ f64 ┆ f64 ┆ f64 ┆ f64 ┆ str │# ╞══════════════╪═════════════╪══════════════╪═════════════╪═══════════╡# │ 7.6 ┆ 3.0 ┆ 6.6 ┆ 2.1 ┆ virginica │# │ 7.3 ┆ 2.9 ┆ 6.3 ┆ 1.8 ┆ virginica │# │ 7.2 ┆ 3.6 ┆ 6.1 ┆ 2.5 ┆ virginica │# │ 7.7 ┆ 3.8 ┆ 6.7 ┆ 2.2 ┆ virginica │# │ ... ┆ ... ┆ ... ┆ ... ┆ ... │# │ 7.7 ┆ 2.8 ┆ 6.7 ┆ 2.0 ┆ virginica │# │ 7.4 ┆ 2.8 ┆ 6.1 ┆ 1.9 ┆ virginica │# │ 7.9 ┆ 3.8 ┆ 6.4 ┆ 2.0 ┆ virginica │# │ 7.7 ┆ 3.0 ┆ 6.1 ┆ 2.3 ┆ virginica │# └──────────────┴─────────────┴──────────────┴─────────────┴───────────┘# 列同士の比較(sepal_widthの値がpetal_lengthより大きいデータのみ抽出)print(df.filter(pl.col('species') == 'virginica'))# shape: (50, 5)# ┌──────────────┬─────────────┬──────────────┬─────────────┬─────────┐# │ sepal_length ┆ sepal_width ┆ petal_length ┆ petal_width ┆ species │# │ --- ┆ --- ┆ --- ┆ --- ┆ --- │# │ f64 ┆ f64 ┆ f64 ┆ f64 ┆ str │# ╞══════════════╪═════════════╪══════════════╪═════════════╪═════════╡# │ 5.1 ┆ 3.5 ┆ 1.4 ┆ 0.2 ┆ setosa │# │ 4.9 ┆ 3.0 ┆ 1.4 ┆ 0.2 ┆ setosa │# │ 4.7 ┆ 3.2 ┆ 1.3 ┆ 0.2 ┆ setosa │# │ 4.6 ┆ 3.1 ┆ 1.5 ┆ 0.2 ┆ setosa │# │ ... ┆ ... ┆ ... ┆ ... ┆ ... │# │ 5.1 ┆ 3.8 ┆ 1.6 ┆ 0.2 ┆ setosa │# │ 4.6 ┆ 3.2 ┆ 1.4 ┆ 0.2 ┆ setosa │# │ 5.3 ┆ 3.7 ┆ 1.5 ┆ 0.2 ┆ setosa │# │ 5.0 ┆ 3.3 ┆ 1.4 ┆ 0.2 ┆ setosa │# └──────────────┴─────────────┴──────────────┴─────────────┴─────────┘
列の抽出と追加
pandasと同じように列名を指定することでSeriesを取得することが出来ます。
print(df['sepal_length'])# shape: (150,)# Series: 'sepal_length' [f64]# [# 5.1# 4.9# 4.7# 4.6# 5.0# 5.4# 4.6# 5.0# 4.4# 4.9# 5.4# 4.8# ...# 6.4# 6.0# 6.9# 6.7# 6.9# 5.8# 6.8# 6.7# 6.7# 6.3# 6.5# 6.2# 5.9# ]
データフレーム形式で取得したい場合、複数列取得したい場合はselect()を使用することで可能です。
print(df.select('sepal_length'))# shape: (150, 1)# ┌──────────────┐# │ sepal_length │# │ --- │# │ f64 │# ╞══════════════╡# │ 5.1 │# │ 4.9 │# │ 4.7 │# │ 4.6 │# │ ... │# │ 6.3 │# │ 6.5 │# │ 6.2 │# │ 5.9 │# └──────────────┘print(df.select(['sepal_length', 'species']))# shape: (150, 2)# ┌──────────────┬───────────┐# │ sepal_length ┆ species │# │ --- ┆ --- │# │ f64 ┆ str │# ╞══════════════╪═══════════╡# │ 5.1 ┆ setosa │# │ 4.9 ┆ setosa │# │ 4.7 ┆ setosa │# │ 4.6 ┆ setosa │# │ ... ┆ ... │# │ 6.3 ┆ virginica │# │ 6.5 ┆ virginica │# │ 6.2 ┆ virginica │# │ 5.9 ┆ virginica │# └──────────────┴───────────┘
また、「行の抽出」で使用したfilter()と同じようにselect()でも「Expressions」を使用することが出来ます。
例えば、下記の様にすることでsepal_length列のすべてのデータにに10を足したデータを取得することが出来ます。
print(df.select(pl.col('sepal_length')+10))# shape: (150, 1)# ┌──────────────┐# │ sepal_length │# │ --- │# │ f64 │# ╞══════════════╡# │ 15.1 │# │ 14.9 │# │ 14.7 │# │ 14.6 │# │ ... │# │ 16.3 │# │ 16.5 │# │ 16.2 │# │ 15.9 │# └──────────────┘
また、polarsではwith_columns()を使用することで列の追加が可能です。
先ほど作成したデータを新しい列として追加してみます。
ここで1点注意すべきなのがカラム名です。
polarsでは列名の重複が許されていないため
alias()を使用して新しい列名を指定します。
print(df.with_columns((pl.col('sepal_length')+10).alias('additional')))# shape: (150, 6)# ┌──────────────┬─────────────┬──────────────┬─────────────┬───────────┬────────────┐# │ sepal_length ┆ sepal_width ┆ petal_length ┆ petal_width ┆ species ┆ additional │# │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │# │ f64 ┆ f64 ┆ f64 ┆ f64 ┆ str ┆ f64 │# ╞══════════════╪═════════════╪══════════════╪═════════════╪═══════════╪════════════╡# │ 5.1 ┆ 3.5 ┆ 1.4 ┆ 0.2 ┆ setosa ┆ 15.1 │# │ 4.9 ┆ 3.0 ┆ 1.4 ┆ 0.2 ┆ setosa ┆ 14.9 │# │ 4.7 ┆ 3.2 ┆ 1.3 ┆ 0.2 ┆ setosa ┆ 14.7 │# │ 4.6 ┆ 3.1 ┆ 1.5 ┆ 0.2 ┆ setosa ┆ 14.6 │# │ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... │# │ 6.3 ┆ 2.5 ┆ 5.0 ┆ 1.9 ┆ virginica ┆ 16.3 │# │ 6.5 ┆ 3.0 ┆ 5.2 ┆ 2.0 ┆ virginica ┆ 16.5 │# │ 6.2 ┆ 3.4 ┆ 5.4 ┆ 2.3 ┆ virginica ┆ 16.2 │# │ 5.9 ┆ 3.0 ┆ 5.1 ┆ 1.8 ┆ virginica ┆ 15.9 │# └──────────────┴─────────────┴──────────────┴─────────────┴───────────┴────────────┘
とりあえず軽く触ってみましたが、Expressionsをどれだけ使いこなせるかがポイントの様です。
次回はもう少しExpressions周りの処理を触ってみようと思います。