深入理解 Expectation 类型:Column Map Expectations、Column Aggregate Expectations、Table Expectations
Great Expectations 的核心,说白了就是一套「断言」系统。你告诉它数据应该长什么样,它去检查,然后告诉你过没过。但数据检查的场景千差万别——有的要逐行扫描,有的要算个总数,有的要看整张表的元数据。所以框架把 Expectation 分成了三大类。
我个人习惯把这三种类型比作「显微镜」、「温度计」和「X光机」。显微镜看细节,温度计量整体,X光机看结构。下面我们一个一个拆开讲。
2.1 Column Map Expectations:逐行扫描的「显微镜」
这类 Expectation 是最常用的。它对每一列、每一行应用一个函数,返回一个布尔值。说白了就是「这行数据符不符合规则?」。
举个例子,你有一个「年龄」列,要求所有值都大于 0。用 expect_column_values_to_be_between 就能搞定。框架会遍历每一行,把不符合条件的行标记出来。
# 检查 age 列是否都在 0 到 150 之间
expectation = ExpectColumnValuesToBeBetween(
column="age",
min_value=0,
max_value=150
)
result = expectation(configuration)
print(result.success) # True 或 False
print(result["unexpected_list"]) # 不符合条件的值列表
我在项目中遇到过一个问题:数据量上亿时,逐行检查非常慢。后来发现 mostly 参数可以救场——它允许一定比例的异常值通过。比如 mostly=0.95 表示允许 5% 的数据不合格。这个参数在数据质量容忍度高的场景下特别好用。
unexpected_list 的长度。如果异常值太多,列表会截断。建议配合 result_metrics 里的 unexpected_percent 一起看。
常见的 Column Map Expectations 包括:
expect_column_values_to_not_be_null— 非空检查expect_column_values_to_be_unique— 唯一性检查expect_column_values_to_match_regex— 正则匹配expect_column_values_to_be_in_set— 枚举值检查expect_column_values_to_be_between— 范围检查
2.2 Column Aggregate Expectations:看整体的「温度计」
这类 Expectation 不关心具体哪行数据有问题,它只看聚合后的统计量。比如平均值、最大值、标准差、唯一值数量等等。
你想想看,有时候你并不需要知道哪条数据错了,你只需要知道「这个月的平均销售额是不是在合理范围内」。这时候 Column Aggregate Expectations 就派上用场了。
# 检查 price 列的平均值是否在 100 到 500 之间
expectation = ExpectColumnMeanToBeBetween(
column="price",
min_value=100,
max_value=500
)
result = expectation(configuration)
print(result.success)
print(result["observed_value"]) # 实际平均值
我记得有一次做金融风控数据校验,客户要求「每日交易金额的方差不能超过历史均值的 3 倍」。用 expect_column_stdev_to_be_between 配合动态阈值,一行代码就搞定了。要是手写 SQL 做同样的事,得写好几层子查询。
expect_column_mean_to_be_between,结果平均值被拉偏了。后来养成了习惯——用 Aggregate Expectations 之前,先跑一个 expect_column_values_to_not_be_null 确认空值率。
常用的 Column Aggregate Expectations:
| Expectation 名称 | 检查内容 | 典型场景 |
|---|---|---|
expect_column_mean_to_be_between |
平均值是否在范围内 | 销售额、温度等连续值 |
expect_column_median_to_be_between |
中位数是否在范围内 | 收入分布、房价等偏态数据 |
expect_column_stdev_to_be_between |
标准差是否在范围内 | 波动性监控、异常检测 |
expect_column_unique_value_count_to_be_between |
唯一值数量是否在范围内 | 分类列、ID 列完整性 |
expect_column_sum_to_be_between |
总和是否在范围内 | 金额、数量等累加值 |
2.3 Table Expectations:看结构的「X光机」
这类 Expectation 不关心具体列里的数据值,它关心的是整张表的元数据——列数、行数、列名、表结构等等。
嗯,这里要注意:Table Expectations 通常是在数据加载完成后第一个跑的。如果表结构都不对,后面的列级检查全是白费功夫。
# 检查表是否有恰好 15 列
expectation = ExpectTableColumnCountToEqual(
value=15
)
result = expectation(configuration)
print(result.success)
# 检查表行数是否在 1000 到 10000 之间
expectation = ExpectTableRowCountToBeBetween(
min_value=1000,
max_value=10000
)
result = expectation(configuration)
我曾经接手过一个数据管道,上游改了 schema 但没通知下游。结果下游的 ETL 跑了三天,全跑在错误的列名上。后来我在管道入口加了一个 expect_table_columns_to_match_ordered_list,列名对不上就直接报错。从那以后,这种「幽灵问题」再也没出现过。
常见的 Table Expectations:
expect_table_row_count_to_be_between— 行数范围expect_table_column_count_to_equal— 列数精确匹配expect_table_columns_to_match_ordered_list— 列名顺序匹配expect_table_columns_to_match_set— 列名集合匹配(不关心顺序)
2.4 三类 Expectation 的关系与选择
这三类不是互斥的,而是互补的。一个完整的数据质量检查套件,通常三者都要用。我画了一张图来展示它们的关系:
从图中你能看到,三种类型覆盖了数据质量的不同维度。实际项目中,我通常这样组合:
- 先跑 Table Expectations — 确认表结构、行数、列名正确
- 再跑 Column Aggregate Expectations — 确认关键列的统计量在合理范围
- 最后跑 Column Map Expectations — 对关键字段做逐行精细检查
2.5 如何选择正确的 Expectation 类型
这个问题没有标准答案,但我有一个简单的判断方法:
- 你想知道「哪条数据有问题」? → 用 Column Map
- 你只想知道「整体趋势对不对」? → 用 Column Aggregate
- 你想确认「表本身有没有变」? → 用 Table
举个例子。你在监控一个电商订单表:
- 想知道有没有订单金额为负数?→
expect_column_values_to_be_between(Column Map) - 想知道今天的平均客单价是否在正常范围?→
expect_column_mean_to_be_between(Column Aggregate) - 想知道今天的数据表有没有新增或删除列?→
expect_table_column_count_to_equal(Table)
这三种类型,加上它们各自的参数配置,基本能覆盖 90% 的数据质量检查场景。剩下的 10%,就需要我们自定义 Expectation 了——那是后面章节的内容。