Closed4

Pandas DataFrameのスキーマバリデーションライブラリpandera, dataenforceの比較

niccariniccari

pandasのDataFrameにおいて、型ヒントを使ったとしてもスキーマがわからない問題がしばしばある。
コード量が数行〜十数行程度であればこれでも問題ないが、さらにコード量が増えると以下の問題が発生しやすくなる。

  • (特に複数の関数でDataFrameを扱っている場合) DataFrameが入出力でどうスキーマが変わったかわからない
  • 意図しないスキーマのDataFrameが入力されたとき、コードの処理に失敗する

上記問題を解決するため、スキーマのバリデーションを提供するライブラリとしてpanderadataenforceがある。どちらをどんな場面で使うべきか判断できるよう、それらの違いを調査した

niccariniccari

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()
niccariniccari

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()

niccariniccari

特別な理由がなければpandera使う方向で良さそう

  • 環境構築に掛かる手間は変わらない
  • panderaは2018年から4年近く開発され続けており、production-readyとなっている
  • panderaにおいて、関数での引数・返り値のチェックは check_input, check_outputデコレータで実現できる
このスクラップは2022/11/13にクローズされました