% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/ops.R
\name{ops_na}
\alias{ops_na}
\title{Summarise missing values by column}
\usage{
ops_na(data, threshold = 0, verbose = TRUE)
}
\arguments{
\item{data}{A data.frame or data.table to scan.}

\item{threshold}{(numeric) Columns with \code{pct_na <= threshold} are silenced
from the per-column CLI output. The summary block is always shown.
Default \code{0}: every column with any missing value is listed.}

\item{verbose}{(logical) Print the CLI report. Default \code{TRUE}.}
}
\value{
An invisible data.table with columns \code{column}, \code{n_na}, and \code{pct_na},
sorted by \code{pct_na} descending. \code{n_na} counts both \code{NA} and \code{""}.
Always contains all columns regardless of \code{threshold} (which only affects
CLI output).
}
\description{
Scans each column of a data.frame or data.table and returns the count and
percentage of missing values. Results are sorted by missingness in
descending order. Columns above 10\\% are flagged in red; those between 0\\%
and 10\\% in yellow. A summary block is always printed regardless of
\code{threshold}.
}
\details{
\strong{Missing value definition}: a value is counted as missing if it is \code{NA}
\emph{or} an empty string (\code{""}). Empty strings are treated as missing because
UKB exports frequently use \code{""} as a placeholder for absent text values.
This means \code{n_na} and \code{pct_na} reflect \emph{effective} missingness, not just
\code{is.na()}. Numeric and logical columns are not affected (they cannot hold
\code{""}).
}
\examples{
dt <- ops_toy(n = 100)

# Show all columns with any missing value
ops_na(dt)

# Only list columns with > 10\% missing in the CLI output
ops_na(dt, threshold = 10)

# Programmatic use — retrieve result silently
result <- ops_na(dt, verbose = FALSE)
result[pct_na > 50]
}
