Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

열, 그룹과 스키마의 기대 조건 참조

아래 연산은 from transforms import expectations as E로 가져온 API를 사용합니다. expression을 만든 뒤 Check에 연결합니다.

논리 연산자

표현식통과 조건
E.true()항상 통과
E.false()항상 실패
E.all(e1, e2, ...)모든 하위 조건 통과
E.any(e1, e2, ...)하위 조건 중 하나 이상 통과
E.negate(e1)해당 하위 조건 실패

열 조건을 E.any()로 묶으면 행마다 조건 중 하나를 만족하는지 검사합니다. 다음은 각 행에서 0 < a < 100이고, b > 100 또는 b < 0인 조건입니다.

from transforms import expectations as E

condition = E.all(
    E.col("a").gt(0),
    E.col("a").lt(100),
    E.any(E.col("b").gt(100), E.col("b").lt(0)),
)

예를 들어 E.any(E.col("c1").lt(0), E.col("c1").gt(10))는 서로 다른 행이 각각 다른 조건을 만족하는 것을 허용합니다.

열과 상수 비교

열 조건은 E.col("열_이름")으로 시작합니다.

메서드의미
.gt(number_or_string)초과
.gte(number_or_string)이상
.lt(number_or_string)미만
.lte(number_or_string)이하
.equals(value)같은 값
.not_equals(value)다른 값
.non_null()NULL이 아님
.is_null()NULL임
.is_in(a, b, ...)허용한 값 중 하나
.rlike(pattern)정규식 부분 일치
.has_type(data_type)지정한 자료형
.exists()해당 이름의 열이 존재, 자료형은 제한하지 않음

크기 비교, equals, not_equals, rlike는 NULL 값을 무시하여 통과시킵니다. NULL을 금지하려면 non_null()을 함께 사용합니다. 반면 is_in()은 허용값 목록에 None을 넣지 않으면 NULL에서 실패합니다.

from transforms import expectations as E

age_limit = E.col("age").lt(120)
success_value = E.col("test_column").equals("success")
not_failure = E.col("test_column").not_equals("failure")
nullable_status = E.col("status").is_in("active", "inactive", None)
flight_number = E.col("flight_number").rlike(r"^\D{2}\d{2,4}$")

rlike는 기본적으로 부분 일치이며, 비행 번호 예제는 ^와 $로 전체 문자열을 제한합니다. 조건은 숫자가 아닌 문자 두 개 뒤에 숫자 2~4개입니다.

다른 열과 비교

메서드같은 행에서 검사하는 관계
E.col("c1").equals_col("c2")c1 = c2
E.col("c1").not_equals_col("c2")c1 ≠ c2
E.col("c1").gt_col("c2")c1 > c2
E.col("c1").gte_col("c2")c1 ≥ c2
E.col("c1").lt_col("c2")c1 < c2
E.col("c1").lte_col("c2")c1 ≤ c2

열 전체의 통계 속성

속성을 만든 뒤 .lt(), .gt(), .equals() 같은 비교를 연결합니다.

속성의미예시
.null_percentage()NULL 비율.lt(0.1)이면 10% 미만
.null_count()NULL 개수.gt(100)이면 100개 초과
.distinct_count()서로 다른 값의 개수.equals(5)이면 5개. 0.11.0부터 제공
.approx_distinct_count()근사 distinct 개수.equals(5)로 추정값 비교
.sum()합계, 숫자 열만 지원.equals(5)
.standard_deviation_sample()표본 표준편차, 숫자 열만 지원.gt(5)
.standard_deviation_population()모집단 표준편차, 숫자 열만 지원.gt(5)

approx_distinct_count()는 빠른 근사 계산이며 오차의 상대 표준편차가 최대 5%입니다. 각 개별 추정 오차가 반드시 ±5% 안에 있다는 뜻으로 해석하지 않습니다. 정확한 개수와의 일치가 필요하면 distinct_count()를 사용합니다.

from transforms import expectations as E

few_nulls = E.col("myCol").null_percentage().lt(0.1)
many_nulls = E.col("myCol").null_count().gt(100)
five_values = E.col("myCol").distinct_count().equals(5)
approx_five = E.col("myCol").approx_distinct_count().equals(5)
sum_five = E.col("myCol").sum().equals(5)
sample_deviation = E.col("myCol").standard_deviation_sample().gt(5)
population_deviation = E.col("myCol").standard_deviation_population().gt(5)

Timestamp의 최소/최대 속성과 시간 비교는 Timestamp 조건에서 설명합니다.

배열 열

배열에는 아래 배열 전용 조건을 사용합니다. 일반 scalar 조건이 모두 배열에도 적용된다고 가정하지 않습니다.

조건의미
E.col("array_col").is_in("a", "b", "c")각 배열의 원소가 허용한 값으로만 구성
E.col("array_col").array_contains("a")각 행의 배열에 a가 포함
E.col("array_col").size().gt(1)배열 길이가 1 초과
E.col("array_col").size().equals(2)배열 길이가 2

그룹별 검사와 전체 행 수

E.group_by("col1", "col2", ...)는 열 조합으로 그룹을 만듭니다. 빈 group_by는 전체 데이터셋 하나를 대상으로 합니다.

from transforms import expectations as E

unique_pairs = E.group_by("col1", "col2").is_unique()
large_groups = E.group_by("col1", "col2").count().gt(100)
small_dataset = E.group_by().count().lt(100)
empty_dataset = E.count().equals(0)
three_values_per_group = E.group_by("col1").col("value_col").distinct_count().equals(3)
few_nulls_per_group = E.group_by("col1").col("value_col").null_percentage().lt(0.5)

is_unique()는 열 조합의 유일성을 검사합니다. 그룹별 속성 검사에는 앞서 설명한 열 통계 속성을 사용할 수 있습니다. 마지막 예제는 각 그룹에서 NULL 비율이 50% 미만인지 검사합니다.

기본 키

E.primary_key("c1")는 해당 열이 NULL이 아니며 유일한지 확인합니다. 여러 열을 전달하면 각 열이 NULL이 아니고 열 조합이 유일해야 합니다.

from transforms import expectations as E

object_key = E.primary_key("object_id")
event_key = E.primary_key("time", "event")

여러 열을 각각 독립적으로 유일하게 만드는 조건은 아닙니다. 예를 들어 같은 time에 여러 event가 있어도 조합이 유일하면 됩니다.

열 자료형과 전체 schema

단일 노드는 계산 엔진과 무관하게 Polars 자료형을, Spark는 Spark SQL 자료형을 사용합니다.

import polars as pl
from transforms import expectations as E

age_type = E.col("age").has_type(pl.Int32)
required_columns = E.schema().contains({
    "name": pl.String(),
    "int_list": pl.List(pl.Int32),
})
from pyspark.sql import types as T
from transforms import expectations as E

age_type = E.col("age").has_type(T.LongType())
required_columns = E.schema().contains({
    "id": T.IntegerType(),
    "name": T.StringType(),
})
Schema 메서드조건
.contains(mapping)지정한 열과 자료형을 포함. 추가 열은 허용
.equals(mapping)지정한 열과 자료형에 정확히 일치. 추가 열은 허용하지 않음
.is_subset_of(mapping)실제 모든 열이 지정한 목록 안에 있어야 함. 지정한 열이 실제로 모두 있을 필요는 없음

조건부 검사

E.when(condition, then_condition).otherwise(otherwise_condition)은 첫 조건을 통과한 행에는 then을, 실패한 행에는 otherwise를 적용합니다.

from transforms import expectations as E

conditional = E.when(
    E.col("myCol").gt(0),
    E.col("myOtherCol").is_in("a"),
).otherwise(
    E.col("myOtherCol").is_in("b"),
)

otherwise를 무조건 통과 또는 실패로 두려면 E.true()나 E.false()를 사용합니다. NULL을 무시하는 열 조건을 when에 사용할 때는 그 조건의 NULL 통과 규칙도 함께 고려합니다.

다른 입력에 값이 존재하는지 검사하거나 그 입력과 행 수를 비교하려면 데이터셋 간 조건을 사용합니다.