% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/survey_qc.R
\name{qc_survey_data}
\alias{qc_survey_data}
\title{Run automated quality control on raw survey data}
\usage{
qc_survey_data(
  df,
  datetime_col = "datetime",
  iqr_k = 3,
  max_gradients = NULL,
  apply_flags = FALSE,
  verbose = TRUE
)
}
\arguments{
\item{df}{Dataframe of raw survey measurements.}

\item{datetime_col}{Character or NULL. Name of the datetime column for
temporal gradient checks (default \code{"datetime"}). Set to NULL to skip.}

\item{iqr_k}{Numeric. IQR multiplier for outlier detection (default 3.0;
use 1.5 for stricter QC of high-precision CTD data).}

\item{max_gradients}{Named numeric vector. Maximum allowed absolute change
per unit time (seconds) per variable. Defaults are conservative for typical
towed or lowered deployments.}

\item{apply_flags}{Logical. If TRUE, replace flagged values with NA in the
returned dataframe. If FALSE (default), flags are added but values
preserved for manual review.}

\item{verbose}{Logical. Print QC summary (default TRUE).}
}
\value{
Input dataframe with additional columns:
\verb{qc_flag_<varname>} for each checked variable (\code{"ok"}, \code{"range_fail"},
\code{"outlier"}, \code{"gradient_fail"}, \code{"cross_fail"}),
\code{qc_n_flags} (integer count of flags per row),
\code{qc_status} (\code{"pass"}, \code{"review"}, \code{"fail"} -- fail = 3+ flags on one row).
}
\description{
Detects and flags suspect sensor readings before they enter the suitability
model. Three complementary checks are applied to each numeric column:
\enumerate{
\item \strong{Range check} -- values outside the physically plausible range for that
variable (e.g. temperature above 35degrees C in temperate coastal water, salinity
above 42 PSU) are flagged as \code{"range_fail"}.
\item \strong{Statistical outlier} -- values beyond \code{iqr_k} x IQR from the median
are flagged as \code{"outlier"} (default k = 3, Tukey's outer fence).
\item \strong{Temporal gradient} -- when a \code{datetime} column is present and data is
sorted chronologically, sequential differences exceeding the
\code{max_gradient} threshold are flagged as \code{"gradient_fail"} (instrument
spike or data entry error).
}

Additionally, \strong{cross-variable sanity checks} flag physically implausible
combinations:
\itemize{
\item Dissolved oxygen > 20 mg/L with temperature < 5degrees C (likely sensor error)
\item Salinity < 5 PSU with temperature > 25degrees C (likely freshwater intrusion
instrument error, not a real coastal reading)
\item Chlorophyll_a > 50 ugg/L (extreme bloom or sensor fouling)
}

Flagged values are \strong{not removed} -- they are marked in a \verb{qc_flag_<col>}
column so the user can decide whether to replace with NA, correct, or
accept them. A summary \code{qc_n_flags} column counts total flags per row.
}
\examples{
\donttest{
# Run QC before modelling
survey_qc <- qc_survey_data(survey, datetime_col = "timestamp")

# Inspect flagged rows
flagged <- subset(survey_qc, qc_status \%in\% c("review","fail"))
View(flagged)

# Apply flags (replace flagged values with NA) before scoring
survey_clean <- qc_survey_data(survey, apply_flags = TRUE)
result <- predict_oyster(survey_clean, "ostrea_edulis")
}
}
