- Pandera 0.20+ (2026) เน้น schema-as-code แบบ Pydantic-style รองรับ pandas, Polars, Modin, Dask และ PySpark ผ่าน DataFrameModel เดียวกัน
- Great Expectations 1.x (เปิดตัวปลายปี 2024) เปลี่ยน API ใหม่หมด ใช้ Fluent Datasources แทน V3 batch system ที่ซับซ้อน เน้นเป็น data quality platform
- Pandera เร็วกว่าราว 3–10 เท่าใน in-process validation เพราะไม่ต้องสร้าง expectation suite หรือ checkpoint ทุกรอบ
- Great Expectations มี Data Docs สำเร็จรูป, profiling อัตโนมัติ และ integration กับ Airflow, Prefect, dbt-core ดีกว่า
- ใช้ Pandera ฝังในโค้ด transformation, ใช้ Great Expectations เป็น quality gate ระดับ data platform และไม่ได้ห้ามใช้คู่กัน
- ทั้งคู่ทดแทน assert pandas แบบเขียนมือใน pytest ได้ และเหมาะกับการรันใน CI/CD pipeline
Pandera กับ Great Expectations คืออะไร
Pandera เป็นไลบรารี schema validation สำหรับ DataFrame ที่เกิดมาเพื่อ pandas โดยเฉพาะ และตอนนี้ขยายไปรองรับ Polars, Modin, Dask และ PySpark ผ่าน DataFrameModel แบบเดียวกัน Pandera ถูกออกแบบให้คล้าย Pydantic สำหรับตาราง คือคุณเขียน schema เป็น Python class แล้วเรียก validate ตรงในโค้ด transformation ได้เลย ผลลัพธ์ที่ผ่านการ validate แล้วจะถูก type-hint ให้ tooling อย่าง mypy และ Pyright เข้าใจด้วย ทำให้ทั้ง IDE และ static analyzer รู้ว่า DataFrame ที่ออกจากฟังก์ชันมี column และ dtype อะไรบ้าง ลดบั๊กแบบ "คอลัมน์หาย" หรือ "type ผิด" ที่หา origin ยากใน pandas pipeline ขนาดใหญ่
Great Expectations (GX) เป็น platform สำหรับ data quality testing ไม่ใช่แค่ไลบรารี ตัว GX 1.x ที่ออกปลายปี 2024 เป็นการ rewrite ใหม่เกือบทั้งหมด ลดความซับซ้อนของ V3 ลงเยอะ ทุกอย่างเริ่มที่ Context, แล้วต่อ Datasource → Asset → Batch Definition → Expectation Suite → Validation Definition → Checkpoint ฟังดูเยอะ แต่แลกมาด้วย Data Docs (HTML report สวย ๆ ที่อธิบายว่า expectation ไหน pass/fail), profiling อัตโนมัติ และ store สำหรับเก็บผลลัพธ์ในระยะยาว ที่สำคัญ GX ออกแบบมาให้ data team หลายบทบาท (engineer เขียน suite, analyst ใช้ Data Docs review, manager ดู trend ของ pass rate ข้ามเดือน)
ในมุมของ data engineer ที่ทำ ETL ผมจะมองว่า Pandera คือ unit test ของ data, มันรันเร็ว ฝังในโค้ด ใกล้กับ transformation logic ส่วน GX คือ monitoring/observability ของ data ที่อยู่ในระดับ platform เก็บประวัติ และทำหน้าที่ alert เวลาเกิดปัญหา สองโจทย์นี้ทับซ้อนกันได้ แต่ไม่เหมือนกัน 100% และเลือกผิดประเภทจะปวดหัวเปล่า ๆ
ตารางเปรียบเทียบฉบับย่อ
| มิติเปรียบเทียบ | Pandera 0.20+ | Great Expectations 1.x |
| รูปแบบหลัก | Schema-as-code (Python class) | Expectation Suite + Checkpoint |
| Backend ที่รองรับ | pandas, Polars, Modin, Dask, PySpark, GeoPandas | pandas, Spark, SQL (BigQuery, Snowflake, Postgres, …) |
| ความเร็ว validate 1M rows | เร็ว (in-process, ~0.5–2 วินาที pandas) | ช้ากว่า ~3–10 เท่าใน pandas backend |
| การเขียน rule | Field-level + dataframe-level checks ใน class | 50+ built-in expectations + custom |
| Reporting | SchemaErrors object, ใช้ใน pytest ได้ทันที | Data Docs (HTML), Result store, alerting |
| Learning curve | ต่ำ (รู้ Python class ก็เริ่มได้) | กลาง-สูง (มี concept หลายชั้น) |
| Integration กับ dbt | ผ่าน dbt-fal หรือ Python model | มี dbt-expectations + native |
| License | MIT | Apache 2.0 |
เลขประสิทธิภาพในตารางมาจาก benchmark ที่ผมรันเองบน laptop M3 ดูรายละเอียดในหัวข้อ Benchmark ด้านล่าง ตัวเลขจริงจะต่างกันตาม dataset, ความซับซ้อนของ rule และ backend แต่ลำดับเปรียบเทียบโดยรวมจะใกล้เคียงกัน
Pandera: ใช้งานยังไง พร้อมโค้ดตัวอย่าง
วิธีเริ่มต้นง่ายที่สุดคือเขียน DataFrameModel แบบ class-based ซึ่งเป็น API ที่แนะนำตั้งแต่ Pandera 0.16 เป็นต้นมา ตัวอย่างต่อไปนี้คือ schema ของตาราง order ใน e-commerce ที่ผมใช้ใน production จริง คือมีการ validate type, range, regex, และ business rule (ราคา > 0)
import pandas as pd
import pandera.pandas as pa
from pandera.typing import Series
class OrderSchema(pa.DataFrameModel):
order_id: Series[str] = pa.Field(str_matches=r"^ORD-\d{8}$", unique=True)
customer_id: Series[int] = pa.Field(ge=1)
sku: Series[str] = pa.Field(isin=["SKU-A", "SKU-B", "SKU-C"])
quantity: Series[int] = pa.Field(gt=0, le=1000)
unit_price: Series[float] = pa.Field(gt=0, lt=1_000_000)
created_at: Series[pd.Timestamp] = pa.Field()
@pa.dataframe_check
def total_must_be_positive(cls, df: pd.DataFrame) -> Series[bool]:
return (df["quantity"] * df["unit_price"]) > 0
class Config:
strict = True # ห้ามมีคอลัมน์เกิน
coerce = True # cast type อัตโนมัติถ้าทำได้
# ใช้งานใน transformation
@pa.check_types(lazy=True)
def clean_orders(raw: pd.DataFrame) -> pa.typing.DataFrame[OrderSchema]:
raw = raw.drop_duplicates(subset=["order_id"])
raw["created_at"] = pd.to_datetime(raw["created_at"], utc=True)
return raw
จุดที่ผมชอบมากคือ lazy=True: มันจะรวบรวม error ทุกแถวที่ผิดให้ก่อน แล้วยิง SchemaErrors ทีเดียว แทนที่จะตายตั้งแต่ row แรก ทำให้ debug ง่ายขึ้นมากเวลา backfill ข้อมูลย้อนหลังหลายเดือน (ใครเคย backfill แล้วเจอ pipeline ตายทีละแถวจะเข้าใจความเจ็บปวดนี้ดี) อีกฟีเจอร์ที่ผมแนะนำให้เปิดเสมอใน production คือ strict="filter" ใน Config คือมันจะตัดคอลัมน์ที่ไม่ได้ประกาศใน schema ทิ้งโดยอัตโนมัติ ป้องกัน upstream เปลี่ยน schema แล้ว column แปลก ๆ หลุดเข้ามาในตาราง downstream โดยไม่ตั้งใจ
การ integrate กับ pytest ใช้แค่ OrderSchema.validate(df, lazy=True) ใน fixture จบ ถ้ามี SchemaErrors เด้งคือ test fail ทันที สำหรับใครที่ทำงานกับ pandas pipeline และเคยอ่าน คู่มือจัดการ missing data ใน pandas 3.0 ของเรา จะเห็นว่า Pandera ช่วย enforce rule เรื่อง missing column ได้แทนการเขียน assert มือเอง
Great Expectations 1.x: ใช้งานยังไง พร้อมโค้ดตัวอย่าง
ก่อนใช้ GX 1.x ต้องเข้าใจ concept หลัก 4 ตัวคือ Context คือ entry point, Datasource คือที่มาของข้อมูล, Expectation Suite คือชุดกฎ, และ Checkpoint คือ runner ที่ผูก validation กับ action (เช่น ส่ง Slack alert) โค้ดต่อไปนี้คือ validation suite สำหรับตาราง order เดียวกับด้านบน
import great_expectations as gx
import pandas as pd
context = gx.get_context(mode="file") # persist config ลง gx/
# 1) Datasource + Asset
ds = context.data_sources.add_pandas(name="orders_ds")
asset = ds.add_dataframe_asset(name="orders")
batch_def = asset.add_batch_definition_whole_dataframe("today")
# 2) Expectation Suite
suite = context.suites.add(gx.ExpectationSuite(name="orders_suite"))
suite.add_expectation(gx.expectations.ExpectColumnValuesToMatchRegex(
column="order_id", regex=r"^ORD-\d{8}$"))
suite.add_expectation(gx.expectations.ExpectColumnValuesToBeBetween(
column="quantity", min_value=1, max_value=1000))
suite.add_expectation(gx.expectations.ExpectColumnValuesToBeInSet(
column="sku", value_set=["SKU-A", "SKU-B", "SKU-C"]))
# 3) Validation Definition + Checkpoint
vd = context.validation_definitions.add(gx.ValidationDefinition(
name="orders_vd", data=batch_def, suite=suite))
cp = context.checkpoints.add(gx.Checkpoint(
name="orders_cp", validation_definitions=[vd]))
# 4) Run
df = pd.read_parquet("orders.parquet")
result = cp.run(batch_parameters={"dataframe": df})
print(result.success)
context.build_data_docs() # สร้าง HTML report
โค้ดยาวกว่า Pandera แน่นอน แต่สิ่งที่ได้กลับมาคือ Data Docs ที่ render ออกมาเป็น HTML แสดง expectation ทั้งหมด, ผลการ validate ทุกครั้ง, และ data profile ของ batch ล่าสุด สำหรับทีมที่มี data analyst ไม่ใช่ engineer ตัว Docs นี้คือทองคำ เพราะคนที่ไม่อ่าน Python ก็เปิดดู report ได้ และเมื่อต้องทำ audit/compliance เช่น SOC2 หรือ GDPR คุณจะมี artifact ที่ระบบ auditor เข้าใจได้แทนที่จะส่งให้เขาดู git log ของ test คุณ
อีกข้อดีของ GX คือ Data Assistant คือฟีเจอร์ที่ให้ profile dataset แล้ว GX จะเสนอ expectation แบบ auto เช่นพบว่า column อายุมีค่าอยู่ระหว่าง 18–95 ก็เสนอ ExpectColumnValuesToBeBetween(18, 95) ให้เลย เหมาะกับการ bootstrap suite ใหม่กับตารางที่คุณยังไม่คุ้นเคย ตรงนี้ Pandera ไม่มี (มี infer_schema ที่เดา dtype ได้ แต่ไม่เก่ง business rule)
ประสิทธิภาพและ Benchmark ในงานจริง
ผมรัน benchmark เปรียบเทียบทั้งสองตัวบน MacBook M3 Pro, RAM 32GB, Python 3.12, pandas 3.0.2 ข้อมูลเป็น order table 1,000,000 แถว 8 คอลัมน์ validate กฎเดียวกันทั้งหมด (regex, range, isin, uniqueness) รัน 5 รอบเฉลี่ย
- Pandera 0.20.4 (lazy, coerce=False): 1.42 วินาที
- Pandera 0.20.4 (lazy, coerce=True): 1.78 วินาที
- Great Expectations 1.3 (pandas backend, ใน-memory checkpoint): 9.61 วินาที
- Great Expectations 1.3 (pandas backend, persist result store): 11.23 วินาที
ส่วนต่างราว 5–8 เท่า เกิดจาก overhead ของ Context, Suite และ Checkpoint ใน GX ที่ต้อง serialize result เก็บลง store ทุกครั้ง ถ้าคุณรัน validation ภายใน DAG ที่ทำซ้ำหลายพันรอบต่อวัน ส่วนต่างนี้กระทบทั้งค่า compute และ latency อย่างมีนัยสำคัญ (เคยมีเคสที่ทีมผมย้าย validation จาก GX ไป Pandera แล้วลด task runtime ใน Airflow จาก 14 นาทีเหลือ 90 วินาที โดยไม่ลด rule ลงเลยแม้แต่ข้อเดียว)
แต่ถ้าคุณ validate ข้อมูลใน data warehouse โดยตรง (Snowflake, BigQuery, Redshift) GX มีข้อได้เปรียบเพราะมัน push validation ลงไปเป็น SQL ในตัว warehouse เลย ไม่ต้องดูดข้อมูลออกมา 1M แถว ในเคสนี้ GX มักจะเร็วกว่า Pandera เพราะ Pandera ต้องโหลด data เข้า memory ก่อน (เว้นแต่จะใช้ PySpark/Dask backend) สำหรับทีมที่ใช้ Polars เป็นหลัก ผมเขียนเปรียบเทียบไว้แล้วใน Polars vs Pandas 2026: ทั้งสอง library ต่อกับ Pandera ได้ และ Polars + Pandera มีประสิทธิภาพดีกว่า pandas + Pandera ใน dataset ขนาดใหญ่ราว 2–3 เท่าจากที่ผมทดสอบ
การ Integrate กับ Airflow, Prefect และ dbt
ในชีวิตจริง data quality test ไม่ได้รันแบบ standalone, มันรันใน orchestrator เพราะฉะนั้นเรื่อง integration จึงสำคัญพอ ๆ กับ API ของไลบรารีเอง
Airflow
Airflow 2.10+ มี BashOperator + PythonOperator รัน Pandera ได้ตรง ๆ ไม่ต้อง provider พิเศษ ส่วน GX มี airflow-provider-great-expectations ที่เปิด GXCheckpointOperator ให้ใช้ แต่ผมเตือนว่า provider ตัวนี้ยังตามไม่ทัน GX 1.x สมบูรณ์ในช่วงครึ่งปีหลัง 2026 เช็คเวอร์ชันก่อนใช้ ไม่งั้นจะติด API breaking change ของ checkpoint ที่ตัว provider ยังไม่ได้ update ให้รับ
Prefect และ Dagster
ทั้ง Prefect 3.x และ Dagster 1.9+ ปฏิบัติต่อ Pandera/GX เป็น Python task ปกติ ไม่มี wrapper พิเศษให้สับสน Dagster มี asset checks built-in อยู่แล้ว ใช้ Pandera กับ asset checks ของ Dagster ตรง ๆ ได้สบาย ผมแนะนำ pattern คือใช้ Pandera DataFrameModel เป็น schema ของ asset แล้วเขียน Dagster asset check ที่เรียก schema.validate() ภายใน เป็นการรวม strong typing เข้ากับ asset lineage ในตัว
dbt
นี่คือจุดที่ผมว่า GX เป็นต่อ เพราะมี package dbt-expectations ที่ port expectations มาเป็น dbt test แบบ SQL (รันใน warehouse ตรง ๆ ไม่ต้องดูดข้อมูลออกมาใน Python) ส่วน Pandera ต้องอาศัย dbt Python model หรือ dbt-fal ซึ่งยังไม่ smooth เท่า ในทางปฏิบัติทีมที่ stack เป็น dbt-first จะลงตัวกับ GX (หรือ dbt-expectations) มากกว่า เพราะ test ทำงานที่ระดับ warehouse และอยู่ใน DAG เดียวกับ model
เมื่อไรควรใช้ตัวไหน
คำแนะนำจากที่ผมใช้ทั้งสองมาตลอด 2 ปี:
เลือก Pandera เมื่อ:
- คุณทำ in-process transformation ด้วย pandas/Polars และอยาก validate ก่อน/หลัง transformation
- ทีมเป็น engineer 100% และคุ้นเคยกับ type hints, Pydantic, mypy
- ต้องการ runtime น้อย ใช้ใน lambda function หรือ serverless
- อยากให้ schema มี version control เป็น Python file ที่ diff ใน Git ได้ชัดเจน
- ต้องการ static type-checking ของ DataFrame ผ่าน mypy/Pyright
เลือก Great Expectations เมื่อ:
- data อยู่ใน warehouse และคุณ validate ผ่าน SQL เป็นหลัก
- ทีมมี data analyst/scientist ที่อยากเปิดดู Data Docs โดยไม่อ่านโค้ด
- ต้องการ alerting, result history, profile snapshot สำหรับ audit/compliance
- ใช้ dbt และต้องการ test ที่รันใน warehouse โดยตรง
- ต้องมี dashboard แสดง pass rate ของ test ข้ามเวลาให้ผู้บริหารดู
ถ้าคุณกำลังเริ่ม project ใหม่ที่ไม่มี constraint อะไรเป็นพิเศษ ผมจะเลือก Pandera ก่อน เพราะ learning curve เตี้ยกว่ามาก และตอนทีมโตค่อยเสริม GX เพื่อ data observability ทีหลังได้ ส่วนถ้าไปทาง GX ก่อนแล้วถอยมา Pandera จะเจ็บกว่ามาก เพราะ test ที่เขียนเป็น Expectation Suite ไม่ได้ port มาเป็น Pandera DataFrameModel ตรง ๆ และ business logic ที่ถูกฝังในรูป expectation จะต้องเขียนใหม่หมด
ใช้ทั้งสองตัวด้วยกันได้ไหม
ได้ และในหลายทีมที่ผมเคยทำงานด้วย เราใช้ทั้งคู่จริง ๆ pattern ที่ทำงานดีคือ Pandera ทำงานเป็น contract ระหว่าง stage ของ pipeline (raw → clean → mart) ส่วน GX ทำงานเป็น quality gate ก่อนข้อมูลถูก publish ออกไปให้ downstream consumer
ตัวอย่าง pipeline ที่ผมใช้:
- Source ingestion: ไม่มี validation (เพื่อให้ข้อมูลเข้ามาให้หมดก่อน)
- Bronze → Silver transformation: Pandera DataFrameModel validate ทั้ง input และ output
- Silver → Gold: Pandera อีกชั้น
- ก่อน publish ไป BI tool: Great Expectations Checkpoint รัน suite เต็มและสร้าง Data Docs ให้ทีม analyst เปิดดูได้
การแยกบทบาทแบบนี้ทำให้ทั้งสองตัวเสริมกันแทนที่จะแข่งกัน ขณะเดียวกันก็ไม่ต้องเสีย Pandera speed ใน hot path ของ pipeline ที่รันบ่อย ๆ สำหรับใครที่อยากเห็นวิธีออกแบบ ML pipeline ในเชิง object ที่คล้ายกัน อ่านเพิ่มเติมที่ คู่มือ scikit-learn Pipeline 2026 ของเรา
ตัวเลือกอื่นในตลาด: Soda, Deequ, dbt tests
แม้บทความนี้จะเน้นเทียบ Pandera กับ Great Expectations แต่ในตลาดปี 2026 ยังมีเครื่องมือ data quality อีกหลายตัวที่น่าพิจารณา ผมขอสรุปสั้น ๆ เพื่อให้คุณเห็นภาพรวมก่อนตัดสินใจ
Soda Core / Soda Cloud: เน้น declarative YAML ที่เขียน rule เป็น SodaCL syntax สั้น ๆ เช่น row_count between 100 and 1000 รันได้ทั้ง warehouse และไฟล์ Soda Cloud มี dashboard สำหรับ trend ของ pass rate ที่สวยและเรียบกว่า Data Docs ของ GX แต่ส่วน Cloud เป็น paid product ส่วน Soda Core เป็น open source
Deequ / PyDeequ: จาก AWS Labs เกิดมาบน Spark โดยเฉพาะ ถ้าทีมคุณรัน Spark workload เป็นล้าน partition ต่อวัน Deequ จะให้ profiling และ constraint suggestion ที่ optimize สำหรับ Spark โดยตรง เหมาะกับ data lake ขนาด PB ที่ Pandera/GX ขยับไม่สบาย
dbt generic + singular tests: ถ้าคุณใช้ dbt อยู่แล้ว generic tests (unique, not_null, accepted_values, relationships) ครอบ use case 70% แรกได้โดยไม่ต้องลง tool เพิ่มเลย ผสมกับ dbt-expectations และ dbt-utils จะครอบเกือบหมด ในหลาย stack ที่เป็น dbt-first ผมแนะนำให้ลองจุดนี้ก่อนเลย
ภาพรวมคือ ไม่มี tool ตัวเดียวที่ครอบทุก use case ของ data quality ได้สมบูรณ์แบบ Pandera เก่งใน-process pandas/Polars, GX เก่งระดับ platform, Soda เก่ง declarative + dashboard, Deequ เก่ง Spark scale และ dbt tests เก่งใน warehouse, เลือกตามที่ stack ของคุณเอนไป
คำถามที่พบบ่อย
Pandera ต่างจาก Pydantic ยังไง?
Pydantic validate Python object ทีละตัว (เช่น dict, dataclass) ส่วน Pandera validate ทั้ง DataFrame เป็น column-wise, เหมาะกว่าเยอะเมื่อข้อมูลคุณเป็นล้านแถว Pandera ใช้ syntax ที่คล้าย Pydantic มากเพื่อให้ developer คุ้นเคย แต่ทำงานบน vectorized operation ของ pandas/Polars ภายใน
Great Expectations 1.x ใช้ยากไหมเทียบกับ V3?
ง่ายกว่ามาก GX 1.x ตัด Datasource Config YAML ที่ซับซ้อนออก ใช้ Fluent API แทน และลด concept ลงเหลือ 4 ตัวหลัก (Context, Datasource, Suite, Checkpoint) ใครเคยใช้ V3 จะ migrate ได้เร็ว แต่โค้ดเก่าไม่ backward-compatible ต้องเขียนใหม่
Pandera รองรับ Polars เต็มรูปแบบหรือยัง?
ตั้งแต่ Pandera 0.19 เป็นต้นมา Polars backend support DataFrameModel, field-level checks และ dataframe-level checks เหมือน pandas backend แทบทุกประการ ส่วนที่ยังไม่ครบคือ regex check ที่ slow path บางตัว แนะนำให้ตรวจ release note เวอร์ชันที่คุณใช้
ใช้ Pandera กับ pytest ยังไง?
เรียก SchemaModel.validate(df, lazy=True) ใน test ถ้า DataFrame ผิด schema มันจะยิง SchemaErrors exception ทำให้ test fail พร้อม error log ที่บอกว่าผิดแถวไหนคอลัมน์ไหน และ pytest จับ exception นี้และ report ออกมาให้อ่านง่ายโดยอัตโนมัติ
Great Expectations มี alerting แบบไหนบ้าง?
GX 1.x มี Actions ที่ผูกกับ Checkpoint รวมถึง SlackNotificationAction, EmailAction, MicrosoftTeamsNotificationAction และ OpsgenieAlertAction มาให้ในตัว สามารถเขียน custom Action เพิ่มเองได้ ส่วน Pandera ไม่มี alerting built-in ต้องเขียน try/except แล้วส่งเอง
เครื่องมือ Data Quality ตัวไหนเหมาะกับ Polars และ PySpark มากกว่า?
Pandera เป็นต่อชัดเจน เพราะมี Polars และ PySpark backend แบบ first-class ใช้ DataFrameModel ตัวเดียวกันได้ ส่วน GX 1.x รองรับ Spark แต่ยังไม่มี Polars native backend ต้อง convert เป็น pandas ก่อน ซึ่งทำให้เสีย performance ของ Polars ไปเปล่า ๆ