bhylu.com

Advertisements

R Data Validation

Check keys, schema and counts before producing a summary.

How it works

A data frame does not enforce an application schema. Validate required names, allowed types, unique keys and row limits before calculations or joins. This fictional importer permits missing visit counts but rejects NaN, infinities and invalid whole counts. Missing observations remain distinct from zero. The validator returns its input invisibly so a caller can keep the original data.

Run this R example

These examples run locally with R, not PHP, Python or JavaScript. The reviewed baseline is R 4.5.2 on Windows x64/UCRT, using only packages shipped with R. This is a tested version, not a newest-release claim. Install your own R from the official R project; an IDE is optional. Save the complete source as data-validation.R in a separate learning folder and run Rscript --vanilla data-validation.R. Keep code and fictional fixtures separate from a real project.

Bhylu has no R browser runner. There is no Try in playground link because the existing Python and JavaScript editors do not execute R. No package installation, account, network dataset, Apache, MySQL or PHP setting is needed to run these base-R sources.

The complete download uses a local scope, restores its temporary options and treats unexpected warnings as errors. Examples that handle an expected warning do so narrowly. Random examples change only their R process’s RNG state. File examples own their temporary output; figure examples leave their named PNG in the current learning folder and refuse to overwrite it. Use a new empty folder to rerun a figure.

Download the complete data-validation.R · Download all source files with hash checks

For the optional collection downloader, save download-examples.mjs in an empty folder and run node download-examples.mjs. Local preview before publishing uses node download-examples.mjs http://127.0.0.1:8000/examples/r/. It refuses an existing bhylu-r-examples folder and does not install or execute R.

Example

data-validation.R

local({
  previous_options <- options(warn = 2, digits = 8, stringsAsFactors = FALSE)
  on.exit(options(previous_options), add = TRUE)
  check_counts <- function(x, allow_missing = FALSE, allow_empty = FALSE) {
    if (!(is.integer(x) || is.double(x)) || is.object(x) || !is.null(dim(x))) {
      stop("Use a plain numeric vector")
    }
    if (length(x) > 256L || (!allow_empty && length(x) == 0L)) {
      stop("Use 1..256 counts unless empty input is explicitly allowed")
    }
    if (any(is.nan(x)) || (!allow_missing && anyNA(x))) {
      stop("Missing or undefined counts are not allowed here")
    }
    observed <- x[!is.na(x)]
    if (any(!is.finite(observed)) || any(observed < 0) ||
        any(observed > 1000000) || any(observed != floor(observed))) {
      stop("Counts must be finite whole numbers from 0 to 1000000")
    }
    invisible(x)
  }

  validate_sessions <- function(data) {
    if (!is.data.frame(data) || !identical(names(data), c("id", "room", "visits"))) {
      stop("Expected id, room and visits columns")
    }
    if (!is.character(data$id) || !is.character(data$room) || anyNA(data$id) ||
        anyNA(data$room) || any(!nzchar(trimws(data$id))) ||
        any(!nzchar(trimws(data$room))) || anyDuplicated(data$id)) {
      stop("Use unique ids and non-empty room labels")
    }
    check_counts(data$visits, allow_missing = TRUE)
    invisible(data)
  }
  sessions <- data.frame(id = c("S1", "S2"), room = c("East", "West"), visits = c(8, NA_real_))
  validate_sessions(sessions)
  cat("valid rows:", nrow(sessions), "unknown counts:", sum(is.na(sessions$visits)), "\n")
  invisible(NULL)
})

Focus on the lesson operations

This excerpt omits the complete script’s option/resource setup. Use the full download to execute it.

Operation excerpt

check_counts <- function(x, allow_missing = FALSE, allow_empty = FALSE) {
  if (!(is.integer(x) || is.double(x)) || is.object(x) || !is.null(dim(x))) {
    stop("Use a plain numeric vector")
  }
  if (length(x) > 256L || (!allow_empty && length(x) == 0L)) {
    stop("Use 1..256 counts unless empty input is explicitly allowed")
  }
  if (any(is.nan(x)) || (!allow_missing && anyNA(x))) {
    stop("Missing or undefined counts are not allowed here")
  }
  observed <- x[!is.na(x)]
  if (any(!is.finite(observed)) || any(observed < 0) ||
      any(observed > 1000000) || any(observed != floor(observed))) {
    stop("Counts must be finite whole numbers from 0 to 1000000")
  }
  invisible(x)
}

validate_sessions <- function(data) {
  if (!is.data.frame(data) || !identical(names(data), c("id", "room", "visits"))) {
    stop("Expected id, room and visits columns")
  }
  if (!is.character(data$id) || !is.character(data$room) || anyNA(data$id) ||
      anyNA(data$room) || any(!nzchar(trimws(data$id))) ||
      any(!nzchar(trimws(data$room))) || anyDuplicated(data$id)) {
    stop("Use unique ids and non-empty room labels")
  }
  check_counts(data$visits, allow_missing = TRUE)
  invisible(data)
}
sessions <- data.frame(id = c("S1", "S2"), room = c("East", "West"), visits = c(8, NA_real_))
validate_sessions(sessions)
cat("valid rows:", nrow(sessions), "unknown counts:", sum(is.na(sessions$visits)), "\n")

Expected result

valid rows: 2 unknown counts: 1

The order of the required columns is part of this deliberately narrow contract. A larger importer might permit a documented optional-column set instead. The boundary review tests malformed shapes, duplicate names, invalid ids and count refusals using this exact function.

For API behaviour, consult the official Introduction to R and your installed help pages. These small examples do not establish real-world statistical conclusions or production performance.

Advertisements