Pandas DataFrameのスキーマバリデーションライブラリpandera, dataenforceの比較
pandasのDataFrameにおいて、型ヒントを使ったとしてもスキーマがわからない問題がしばしばある。
コード量が数行〜十数行程度であればこれでも問題ないが、さらにコード量が増えると以下の問題が発生しやすくなる。
- (特に複数の関数でDataFrameを扱っている場合) DataFrameが入出力でどうスキーマが変わったかわからない
- 意図しないスキーマのDataFrameが入力されたとき、コードの処理に失敗する
上記問題を解決するため、スキーマのバリデーションを提供するライブラリとしてpanderaとdataenforceがある。どちらをどんな場面で使うべきか判断できるよう、それらの違いを調査した
production向けでないテストコードであり、型ヒント or カラムの整合性チェック or カラムの型チェックだけでよいのであればdataenforceを試すことができる。以下の様にして、関数の入出力に対してスキーマのバリデーションを掛けることができる。
from dataenforce import Dataset
from dataenforce import validate
import numpy as np
import pandas as pd
from datetime import datetime
ExampleDataset = Dataset[
"id": np.int64,
"point": np.float64,
"date": np.datetime64,
"name": object,
"nullable": np.float64
]
@validate
def process_data(df: ExampleDataset):
print(df)
print(df.dtypes)
def run():
now = datetime.now()
df = pd.DataFrame({
"id": [1, 2, 3],
"point": [1.0, 2.0, None],
"date": [now, now, now],
"name": ["a", "b", "c"],
"nullable": [1, 2, None] # cast to np.float64
})
process_data(df)
run()
import numpy as np
import pandas as pd
import pandera as pa
from datetime import datetime
example_dataset = pa.DataFrameSchema({
"id": pa.Column(np.int64),
"point": pa.Column(np.float64, nullable=True),
"date": pa.Column(np.datetime64),
"name": pa.Column(object),
"nullable": pa.Column(np.float64, nullable=False)
})
@pa.check_input(example_dataset)
def process_data(df):
print(df)
print(df.dtypes)
def run():
now = datetime.now()
df = pd.DataFrame({
"id": [1, 2, 3],
"point": [1.0, 2.0, None],
"date": [now, now, now],
"name": ["a", "b", "c"],
"nullable": [1, 2, None] # cast to np.float64
})
process_data(df)
run()
特別な理由がなければpandera使う方向で良さそう
- 環境構築に掛かる手間は変わらない
- panderaは2018年から4年近く開発され続けており、production-readyとなっている
- panderaにおいて、関数での引数・返り値のチェックは check_input, check_outputデコレータで実現できる