% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/modify.R
\name{modify}
\alias{modify}
\alias{modify_if}
\alias{modify_at}
\alias{modify2}
\alias{imodify}
\title{Modify elements selectively}
\usage{
modify(.x, .f, ...)

modify_if(.x, .p, .f, ..., .else = NULL)

modify_at(.x, .at, .f, ...)

modify2(.x, .y, .f, ...)

imodify(.x, .f, ...)
}
\arguments{
\item{.x}{A vector.}

\item{.f}{A function specified in the same way as the corresponding map
function.}

\item{...}{Additional arguments passed on to the mapped function.

We now generally recommend against using \code{...} to pass additional
(constant) arguments to \code{.f}. Instead use a shorthand anonymous function:

\if{html}{\out{<div class="sourceCode R">}}\preformatted{# Instead of
x |> map(f, 1, 2, collapse = ",")
# do:
x |> map(\\(x) f(x, 1, 2, collapse = ","))
}\if{html}{\out{</div>}}

This makes it easier to understand which arguments belong to which
function and will tend to yield better error messages.}

\item{.p}{A single predicate function, a formula describing such a
predicate function, or a logical vector of the same length as \code{.x}.
Alternatively, if the elements of \code{.x} are themselves lists of
objects, a string indicating the name of a logical element in the
inner lists. Only those elements where \code{.p} evaluates to
\code{TRUE} will be modified.}

\item{.else}{A function applied to elements of \code{.x} for which \code{.p}
returns \code{FALSE}.}

\item{.at}{A logical, integer, or character vector giving the elements
to select. Alternatively, a function that takes a vector of names,
and returns a logical, integer, or character vector of elements to select.

\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}: if the tidyselect package is
installed, you can use \code{vars()} and tidyselect helpers to select
elements.}

\item{.y}{A vector, usually the same length as \code{.x}.}
}
\value{
An object the same class as \code{.x}
}
\description{
Unlike \code{\link[=map]{map()}} and its variants which always return a fixed object
type (list for \code{map()}, integer vector for \code{map_int()}, etc), the
\code{modify()} family always returns the same type as the input object.
\itemize{
\item \code{modify()} is a shortcut for \verb{x[[i]] <- f(x[[i]]); return(x)}.
\item \code{modify_if()} only modifies the elements of \code{x} that satisfy a
predicate and leaves the others unchanged. \code{modify_at()} only
modifies elements given by names or positions.
\item \code{modify2()} modifies the elements of \code{.x} but also passes the
elements of \code{.y} to \code{.f}, just like \code{\link[=map2]{map2()}}. \code{imodify()} passes
the names or the indices to \code{.f} like \code{\link[=imap]{imap()}} does.
\item \code{\link[=modify_in]{modify_in()}} modifies a single element in a \code{\link[=pluck]{pluck()}} location.
}
}
\details{
Since the transformation can alter the structure of the input; it's
your responsibility to ensure that the transformation produces a
valid output. For example, if you're modifying a data frame, \code{.f}
must preserve the length of the input.
}
\section{Genericity}{


\code{modify()} and variants are generic over classes that implement
\code{length()}, \code{[[} and \verb{[[<-} methods. If the default implementation
is not compatible for your class, you can override them with your
own methods.

If you implement your own \code{modify()} method, make sure it satisfies
the following invariants:

\if{html}{\out{<div class="sourceCode">}}\preformatted{modify(x, identity) === x
modify(x, compose(f, g)) === modify(x, g) |> modify(f)
}\if{html}{\out{</div>}}

These invariants are known as the functor
laws (https://wiki.haskell.org/Functor#Functor_Laws) in computer
science.
}

\examples{
# Convert factors to characters
iris |>
  modify_if(is.factor, as.character) |>
  str()

# Specify which columns to map with a numeric vector of positions:
mtcars |> modify_at(c(1, 4, 5), as.character) |> str()

# Or with a vector of names:
mtcars |> modify_at(c("cyl", "am"), as.character) |> str()

list(x = sample(c(TRUE, FALSE), 100, replace = TRUE), y = 1:100) |>
  list_transpose(simplify = FALSE) |>
  modify_if("x", \(l) list(x = l$x, y = l$y * 100)) |>
  list_transpose()

# Use modify2() to map over two vectors and preserve the type of
# the first one:
x <- c(foo = 1L, bar = 2L)
y <- c(TRUE, FALSE)
modify2(x, y, \(x, cond) if (cond) x else 0L)

# Use a predicate function to decide whether to map a function:
modify_if(iris, is.factor, as.character)

# Specify an alternative with the `.else` argument:
modify_if(iris, is.factor, as.character, .else = as.integer)
}
\seealso{
Other map variants: 
\code{\link{imap}()},
\code{\link{lmap}()},
\code{\link{map}()},
\code{\link{map2}()},
\code{\link{map_depth}()},
\code{\link{map_if}()},
\code{\link{pmap}()}

Other modify variants: 
\code{\link{map_depth}()},
\code{\link{modify_tree}()}
}
\concept{map variants}
\concept{modify variants}
