Skip to contents

Evaluates each rule from rule() and returns the failures in the same shape validate_schema() uses, so the two can be combined and handed to apply_schema_validation() together.

Usage

validate_rules(data, rules)

Arguments

data

A data frame.

rules

A list of rule() objects, or a single rule.

Value

A named list of issues, each with severity, message, and for a row-wise rule n_failed and rows (the first failing row indices). Empty when everything passes.

Details

A rule whose column is absent is SKIPPED rather than failed – a missing column is validate_schema() 's business, and reporting it twice buries the real finding. A rule that ERRORS is reported as a failure naming the error, never swallowed: a rule that cannot run has not passed.

Examples

df <- data.frame(id = c(1, 2, 2), age = c(30, -5, 40),
                 start = c(1, 5, 3), end = c(2, 4, 9))

rules <- list(
  rule("age_non_negative", function(v) v >= 0, column = "age"),
  rule("id_unique", function(v) !anyDuplicated(v), column = "id",
       severity = "fatal"),
  rule("dates_ordered", function(d) all(d$start <= d$end))
)

issues <- validate_rules(df, rules)
names(issues)
#> [1] "age_non_negative" "id_unique"        "dates_ordered"   

# A row-wise failure reports how many rows and which.
issues$age_non_negative$n_failed
#> [1] 1
issues$age_non_negative$rows
#> [1] 2

# Clean data produces nothing.
clean <- data.frame(id = 1:3, age = c(30, 31, 40), start = 1:3, end = 4:6)
length(validate_rules(clean, rules))
#> [1] 0

# A rule for an absent column is skipped, not failed -- a missing
# column is validate_schema()'s finding to report, not this one's.
length(validate_rules(data.frame(id = 1:3), rules[1:2]))
#> [1] 0

# A rule that errors is a failure, not a silent pass.
broken <- list(rule("bad", function(v) stop("boom"), column = "age"))
validate_rules(clean, broken)$bad$message
#> [1] "Rule 'bad' failed (rule could not be evaluated: boom)"