% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/fd_define.R
\name{fd_define}
\alias{fd_define}
\title{Define featdelta feature definitions}
\usage{
fd_define(
  ...,
  defs = NULL,
  description = NULL,
  overwrite = FALSE,
  envir = NULL
)
}
\arguments{
\item{...}{Definitions supplied inline.
Ordinary named inputs such as \code{new_feature = hp / cyl} are stored as
single-column definition steps.}

\item{defs}{Optional list of programmatically supplied definitions.
Supported inputs are the same as for \code{...}.}

\item{description}{Optional character scalar describing the definitions.}

\item{overwrite}{Logical. If \code{FALSE}, duplicate step names are rejected.
If \code{TRUE}, later steps replace earlier ones.}

\item{envir}{Optional environment used as the explicit evaluation
environment for normalized definitions. If \code{NULL}, environments are taken
from the captured inputs.}
}
\value{
A list of class \code{"featdelta_defs"} containing:
\itemize{
\item \code{steps}: ordered normalized definition steps
\item \code{description}: optional description
\item \code{created_at}: creation time
\item \code{defs_version}: internal version marker
\item \code{envir_policy}: whether environments were inherited or explicit
\item \code{envir}: the explicit environment, if supplied
}
}
\description{
Creates a \code{featdelta_defs} object that stores ordered definition steps in a
normalized internal representation suitable for later evaluation by
\code{fd_compute()}.
}
\details{
\code{fd_define()} is the definitions-construction step of the package. It does
not compute features and does not access the database. Its role is to:
\itemize{
\item capture user definitions,
\item normalize supported input styles to a canonical internal structure,
\item enforce definition-level guardrails such as name validity and
duplicate handling,
\item store the resulting ordered definition steps for later execution.
}

Definitions are evaluated later by \code{fd_compute()} in the order they are
stored. This means later definitions may depend on columns created by
earlier steps. Reordering or removing earlier steps may therefore break
downstream definitions.

Supported definition inputs include:
\itemize{
\item inline expressions captured from \code{...}
\item quosures
\item \code{expression()} objects of length 1
\item quoted calls or names
\item direct scalar constants
\item \code{fd_block()} objects for multi-column feature generation
}

Ordinary named expressions define one output column per step.

\code{fd_block()} defines a multi-column step. At compute time, a block is
expected to return a \code{data.frame} with one row per input row. The returned
column names become the produced feature names. Optionally, expected output
names may be declared in advance via \code{fd_block(expected_names = ...)}.

Direct atomic constants must be scalar. If vectorized behavior is desired,
provide an expression instead of embedding a fixed-length atomic vector in
the definitions.

Duplicate step handling is part of definitions construction:
\itemize{
\item with \code{overwrite = FALSE}, duplicate step names error;
\item with \code{overwrite = TRUE}, the last definition wins.
}
}
\examples{
# Single-column definitions
defs <- fd_define(
  hp_per_cyl = hp / cyl,
  wt_per_hp = wt / hp
)

# Definitions can also be supplied programmatically
predef <- expression(log(hp))
defs <- fd_define(
  log_hp = predef
)

# Multi-column block using an inline expression
defs <- fd_define(
  engine_ratios = fd_block({
    data.frame(
      hp_per_cyl = hp / cyl,
      disp_per_cyl = disp / cyl
    )
  })
)

# Multi-column block with declared expected names
defs <- fd_define(
  engine_ratios = fd_block(
    {
      data.frame(
        hp_per_cyl = hp / cyl,
        disp_per_cyl = disp / cyl
      )
    },
    expected_names = c("hp_per_cyl", "disp_per_cyl")
  )
)

# Function-based block
make_engine_features <- function(data) {
  data.frame(
    hp_per_cyl = data$hp / data$cyl,
    disp_per_cyl = data$disp / data$cyl
  )
}

defs <- fd_define(
  engine_ratios = fd_block(make_engine_features)
)

# A block can contain a small feature script with temporary variables
defs <- fd_define(
  engine_script = fd_block({
    hp_per_cyl <- hp / cyl
    disp_per_cyl <- disp / cyl

    data.frame(
      hp_per_cyl = hp_per_cyl,
      disp_per_cyl = disp_per_cyl,
      engine_index = hp_per_cyl + disp_per_cyl
    )
  })
)

# A function-based block can create a variable number of columns in a loop
make_scaled_features <- function(data) {
  vars <- c("hp", "disp", "wt")
  out <- list()

  for (var in vars) {
    center <- mean(data[[var]], na.rm = TRUE)
    spread <- stats::sd(data[[var]], na.rm = TRUE)
    out[[paste0(var, "_scaled")]] <- (data[[var]] - center) / spread
  }

  as.data.frame(out)
}

defs <- fd_define(
  scaled_inputs = fd_block(make_scaled_features)
)

}
\seealso{
Other featdelta defs helpers: 
\code{\link{fd_block}()},
\code{\link{print.featdelta_defs}()},
\code{\link{summary.featdelta_defs}()}
}
\concept{featdelta defs helpers}
