% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/cluster_centroids.R
\name{step_cluster_centroids}
\alias{step_cluster_centroids}
\alias{tidy.step_cluster_centroids}
\title{Under-Sampling by Cluster Centroids}
\usage{
step_cluster_centroids(
  recipe,
  ...,
  role = NA,
  trained = FALSE,
  column = NULL,
  under_ratio = 1,
  voting = "soft",
  skip = TRUE,
  seed = sample.int(10^5, 1),
  distance_with = recipes::all_predictors(),
  id = rand_id("cluster_centroids")
)
}
\arguments{
\item{recipe}{A recipe object. The step will be added to the sequence of
operations for this recipe.}

\item{...}{One or more selector functions to choose which
variable is used to sample the data. See \link[recipes:selections]{recipes::selections}
for more details. The selection should result in \emph{single
factor variable}. For the \code{tidy} method, these are not
currently used.}

\item{role}{Not used by this step since no new variables are
created.}

\item{trained}{A logical to indicate if the quantities for preprocessing have
been estimated.}

\item{column}{A character string of the variable name that will
be populated (eventually) by the \code{...} selectors.}

\item{under_ratio}{A numeric value for the ratio of the
majority-to-minority frequencies. The default value (1) means
that all other levels are sampled down to have the same
frequency as the least occurring level. A value of 2 would mean
that the majority levels will have (at most) (approximately)
twice as many rows than the minority level.

A named numeric vector can be used instead to give different levels
different targets, for example \code{c(a = 2, b = 3)}. The names must be levels
of the outcome and the values are ratios of the minority level, exactly as
in the single-number case. Levels that are not named are left untouched, as
are rows with a missing outcome. Because a vector of targets is not a
single value, supplying one means this argument can no longer be tuned. See
\code{vignette("ratio", package = "themis")} for more details.}

\item{voting}{A character string. Either \code{"soft"} (the default) to use the
cluster centroids themselves, or \code{"hard"} to use the observation closest to
each centroid.}

\item{skip}{A logical. Should the step be skipped when the recipe is baked by
\code{\link[recipes:bake]{bake()}}? While all operations are baked when \code{\link[recipes:prep]{prep()}} is run, some
operations may not be able to be conducted on new data (e.g. processing the
outcome variable(s)). Care should be taken when using \code{skip = TRUE} as it
may affect the computations for subsequent operations.}

\item{seed}{An integer that will be used as the seed when
applied.}

\item{distance_with}{A call to a selector function to choose
which variables are used to compute the clusters. Defaults to
\code{\link[recipes:all_predictors]{recipes::all_predictors()}}. The variable selected by \code{...} is
always excluded from the clustering.}

\item{id}{A character string that is unique to this step to identify it.}
}
\value{
An updated version of \code{recipe} with the new step
added to the sequence of existing steps (if any). For the
\code{tidy} method, a tibble with columns \code{terms} which is
the variable used to sample.
}
\description{
\code{step_cluster_centroids()} creates a \emph{specification} of a recipe step that
removes majority class instances by replacing each majority class with
cluster representatives found with k-means.
}
\details{
Each class larger than the target count is summarized by running k-means on
the observations of that class, using as many clusters as the target count.
The class is then replaced by one representative per cluster:

\describe{
\item{\code{voting = "soft"}}{the cluster centroids themselves are used, so the
returned observations are synthetic points that need not appear in the
input.}
\item{\code{voting = "hard"}}{the observation closest to each centroid is used,
so all returned observations are real rows. The representative is always
picked from the class being under-sampled.}
}

This makes it the one \emph{prototype generation} under-sampler in this package.
The other under-sampling methods perform \emph{prototype selection}, keeping a
subset of the original rows.

Because two clusters can share the same closest observation, \code{voting = "hard"} can return slightly fewer observations than the target count.

All columns in the data are sampled and returned by \code{\link[recipes:juice]{recipes::juice()}}
and \code{\link[recipes:bake]{recipes::bake()}}.

All columns selected by \code{distance_with} must be numeric with no missing
data.

When used in modeling, users should strongly consider using the
option \code{skip = TRUE} so that the extra sampling is \emph{not}
conducted outside of the training set.
}
\section{Non-predictor columns}{
With \code{voting = "soft"} the observations of an under-sampled class are
replaced by synthetic points, and columns that are not selected by
\code{distance_with} have no value for those points. Such columns are set to \code{NA},
as they are for the over-sampling steps that synthesize observations. Use
\code{voting = "hard"} if these columns must be kept intact.
}

\section{Tidying}{
When you \code{\link[recipes:tidy.recipe]{tidy()}} this step, a tibble is returned with
columns \code{terms} and \code{id}:

\describe{
\item{terms}{character, the selectors or variables selected}
\item{id}{character, id of this step}
}
}

\section{Tuning Parameters}{
This step has 1 tuning parameters:
\itemize{
\item \code{under_ratio}: Under-Sampling Ratio (type: double, default: 1)
}
}

\section{Case weights}{


The underlying operation does not allow for case weights. Supplying data
with a case weights column to this step results in an error.
}

\examples{
\dontshow{if (rlang::is_installed("modeldata")) withAutoprint(\{ # examplesIf}
library(recipes)
library(modeldata)
data(hpc_data)

hpc_data0 <- hpc_data |>
  select(-protocol, -day)

orig <- count(hpc_data0, class, name = "orig")
orig

up_rec <- recipe(class ~ ., data = hpc_data0) |>
  # Bring the majority levels down to about 1000 each
  # 1000/259 is approx 3.862
  step_cluster_centroids(class, under_ratio = 3.862) |>
  prep()

training <- up_rec |>
  bake(new_data = NULL) |>
  count(class, name = "training")
training

# Since `skip` defaults to TRUE, baking the step has no effect
baked <- up_rec |>
  bake(new_data = hpc_data0) |>
  count(class, name = "baked")
baked

library(ggplot2)

ggplot(circle_example, aes(x, y, color = class)) +
  geom_point() +
  labs(title = "Without ClusterCentroids") +
  xlim(c(1, 15)) +
  ylim(c(1, 15))

recipe(class ~ x + y, data = circle_example) |>
  step_cluster_centroids(class) |>
  prep() |>
  bake(new_data = NULL) |>
  ggplot(aes(x, y, color = class)) +
  geom_point() +
  labs(title = "With ClusterCentroids") +
  xlim(c(1, 15)) +
  ylim(c(1, 15))
\dontshow{\}) # examplesIf}
}
\seealso{
\code{\link[=cluster_centroids]{cluster_centroids()}} for direct implementation

Other Steps for under-sampling:
\code{\link[=step_cnn]{step_cnn()}},
\code{\link[=step_downsample]{step_downsample()}},
\code{\link[=step_enn]{step_enn()}},
\code{\link[=step_instance_hardness]{step_instance_hardness()}},
\code{\link[=step_ncl]{step_ncl()}},
\code{\link[=step_nearmiss]{step_nearmiss()}},
\code{\link[=step_oss]{step_oss()}},
\code{\link[=step_tomek]{step_tomek()}}
}
\concept{Steps for under-sampling}
