% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/case-match.R
\name{case_match}
\alias{case_match}
\title{A general vectorised \code{switch()}}
\usage{
case_match(.x, ..., .default = NULL, .ptype = NULL)
}
\arguments{
\item{.x}{A vector to match against.}

\item{...}{<\code{\link[rlang:dyn-dots]{dynamic-dots}}> A sequence of two-sided
formulas: \code{old_values ~ new_value}. The right hand side (RHS) determines
the output value for all values of \code{.x} that match the left hand side
(LHS).

The LHS must evaluate to the same type of vector as \code{.x}. It can be any
length, allowing you to map multiple \code{.x} values to the same RHS value.
If a value is repeated in the LHS, i.e. a value in \code{.x} matches to
multiple cases, the first match is used.

The RHS inputs will be coerced to their common type. Each RHS input will be
\link[vctrs:theory-faq-recycling]{recycled} to the size of \code{.x}.}

\item{.default}{The value used when values in \code{.x} aren't matched by any of
the LHS inputs. If \code{NULL}, the default, a missing value will be used.

\code{.default} is \link[vctrs:theory-faq-recycling]{recycled} to the size of
\code{.x}.}

\item{.ptype}{An optional prototype declaring the desired output type. If
not supplied, the output type will be taken from the common type of
all RHS inputs and \code{.default}.}
}
\value{
A vector with the same size as \code{.x} and the same type as the common type of
the RHS inputs and \code{.default} (if not overridden by \code{.ptype}).
}
\description{
\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}

\code{case_match()} is deprecated. Please use \code{\link[=recode_values]{recode_values()}} and
\code{\link[=replace_values]{replace_values()}} instead, which are more powerful, have more intuitive
names, and have better safety. In addition to the familiar two-sided formula
interface, these functions also have \code{from} and \code{to} arguments which allow
you to incorporate a lookup table into the recoding process.

This function allows you to vectorise multiple \code{\link[=switch]{switch()}} statements. Each
case is evaluated sequentially and the first match for each element
determines the corresponding value in the output vector. If no cases match,
the \code{.default} is used.
}
\examples{
# `case_match()` is deprecated and has been replaced by `recode_values()` and
# `replace_values()`

x <- c("a", "b", "a", "d", "b", NA, "c", "e")

# `recode_values()` is a 1:1 replacement for `case_match()`
case_match(
  x,
  "a" ~ 1,
  "b" ~ 2,
  "c" ~ 3,
  "d" ~ 4
)
recode_values(
  x,
  "a" ~ 1,
  "b" ~ 2,
  "c" ~ 3,
  "d" ~ 4
)

# `recode_values()` has an additional `unmatched` argument to help you catch
# missed mappings
try(recode_values(
  x,
  "a" ~ 1,
  "b" ~ 2,
  "c" ~ 3,
  "d" ~ 4,
  unmatched = "error"
))

# `recode_values()` also has additional `from` and `to` arguments, which are
# useful when your lookup table is defined elsewhere (for example, it could
# be read in from a CSV file). This is very difficult to do with
# `case_match()`!
lookup <- tribble(
  ~from, ~to,
  "a", 1,
  "b", 2,
  "c", 3,
  "d", 4
)

recode_values(x, from = lookup$from, to = lookup$to)

# Both `case_match()` and `recode_values()` work with more than just
# character inputs:
y <- as.integer(c(1, 2, 1, 3, 1, NA, 2, 4))

case_match(
  y,
  c(1, 3) ~ "odd",
  c(2, 4) ~ "even",
  .default = "missing"
)
recode_values(
  y,
  c(1, 3) ~ "odd",
  c(2, 4) ~ "even",
  default = "missing"
)

# Or with a lookup table
lookup <- tribble(
  ~from,   ~to,
  c(1, 3), "odd",
  c(2, 4), "even"
)
recode_values(y, from = lookup$from, to = lookup$to, default = "missing")

# `replace_values()` is a convenient way to replace selected values, leaving
# everything else as is. It's similar to `case_match(y, .default = y)`.
replace_values(y, NA ~ 0)
case_match(y, NA ~ 0, .default = y)

# Notably, `replace_values()` is type stable, which means that `y` can't
# change types out from under you, unlike with `case_match()`!
typeof(y)
typeof(replace_values(y, NA ~ 0))
typeof(case_match(y, NA ~ 0, .default = y))

# We believe that `replace_values()` better expresses intent when doing a
# partial replacement. Compare these two `mutate()` calls, each with the
# goals of:
# - Replace missings in `hair_color`
# - Replace some of the `species`
starwars |>
  mutate(
    hair_color = case_match(hair_color, NA ~ "unknown", .default = hair_color),
    species = case_match(
      species,
      "Human" ~ "Humanoid",
      "Droid" ~ "Robot",
      c("Wookiee", "Ewok") ~ "Hairy",
      .default = species
    ),
    .keep = "used"
  )

updates <- tribble(
  ~from,                ~to,
  "Human",              "Humanoid",
  "Droid",              "Robot",
  c("Wookiee", "Ewok"), "Hairy"
)

starwars |>
  mutate(
    hair_color = replace_values(hair_color, NA ~ "unknown"),
    species = replace_values(species, from = updates$from, to = updates$to),
    .keep = "used"
  )
}
\keyword{internal}
