% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/data_modify.R
\name{data_modify}
\alias{data_modify}
\alias{data_modify.data.frame}
\title{Create new variables in a data frame}
\usage{
data_modify(data, ...)

\method{data_modify}{data.frame}(data, ..., .if = NULL, .at = NULL, .modify = NULL)
}
\arguments{
\item{data}{A data frame}

\item{...}{One or more expressions that define the new variable name and the
values or recoding of those new variables. These expressions can be one of:
\itemize{
\item A sequence of named, literal expressions, where the left-hand side refers
to the name of the new variable, while the right-hand side represent the
values of the new variable. Example: \code{Sepal.Width = center(Sepal.Width)}.
\item A vector of length 1 (which will be recycled to match the number of rows
in the data), or of same length as the data.
\item A variable that contains a value to be used. Example:

\if{html}{\out{<div class="sourceCode r">}}\preformatted{a <- "abc"
data_modify(iris, var_abc = a) # var_abc contains "abc"
}\if{html}{\out{</div>}}
\item An expression can also be provided as string and wrapped in
\code{as_expr()}. Example:

\if{html}{\out{<div class="sourceCode r">}}\preformatted{data_modify(iris, as_expr("Sepal.Width = center(Sepal.Width)"))
# or
a <- "center(Sepal.Width)"
data_modify(iris, Sepal.Width = as_expr(a))
# or
a <- "Sepal.Width = center(Sepal.Width)"
data_modify(iris, as_expr(a))
}\if{html}{\out{</div>}}

Note that \code{as_expr()} is no real function, which cannot be used outside
of \code{data_modify()}, and hence it is not exported nor documented. Rather,
it is only used for internally processing expressions.
\item Using \code{NULL} as right-hand side removes a variable from the data frame.
Example: \code{Petal.Width = NULL}.
\item For data frames (including grouped ones), the function \code{n()} can be used to
count the number of observations and thereby, for instance, create index
values by using \code{id = 1:n()} or \code{id = 3:(n()+2)} and similar. Note that,
like \code{as_expr()}, \code{n()} is also no true function and cannot be used outside
of \code{data_modify()}.
}

Note that newly created variables can be used in subsequent expressions,
including \code{.at} or \code{.if}. See also 'Examples'.}

\item{.if}{A function that returns \code{TRUE} for columns in the data frame where
\code{.if} applies. This argument is used in combination with the \code{.modify} argument.
Note that only one of \code{.at} or \code{.if} can be provided, but not both at the same
time. Newly created variables in \code{...} can also be selected, see 'Examples'.}

\item{.at}{A character vector of variable names that should be modified. This
argument is used in combination with the \code{.modify} argument. Note that only one
of \code{.at} or \code{.if} can be provided, but not both at the same time. Newly created
variables in \code{...} can also be selected, see 'Examples'.}

\item{.modify}{A function that modifies the variables defined in \code{.at} or \code{.if}.
This argument is used in combination with either the \code{.at} or the \code{.if} argument.
Note that the modified variable (i.e. the result from \code{.modify}) must be either
of length 1 or of same length as the input variable.}
}
\description{
Create new variables or modify existing variables in a data frame. Unlike \code{base::transform()}, \code{data_modify()}
can be used on grouped data frames, and newly created variables can be directly
used.
}
\note{
\code{data_modify()} can also be used inside functions. However, it is
recommended to pass the recode-expression as character vector or list of
characters.
}
\examples{
data(efc)
new_efc <- data_modify(
  efc,
  c12hour_c = center(c12hour),
  c12hour_z = c12hour_c / sd(c12hour, na.rm = TRUE),
  c12hour_z2 = standardize(c12hour)
)
head(new_efc)

# using strings instead of literal expressions
new_efc <- data_modify(
  efc,
  as_expr("c12hour_c = center(c12hour)"),
  as_expr("c12hour_z = c12hour_c / sd(c12hour, na.rm = TRUE)"),
  as_expr("c12hour_z2 = standardize(c12hour)")
)
head(new_efc)

# using a character vector, provided a variable
xpr <- c(
  "c12hour_c = center(c12hour)",
  "c12hour_z = c12hour_c / sd(c12hour, na.rm = TRUE)",
  "c12hour_z2 = standardize(c12hour)"
)
new_efc <- data_modify(efc, as_expr(xpr))
head(new_efc)

# using character strings, provided as variable
stand <- "c12hour_c / sd(c12hour, na.rm = TRUE)"
new_efc <- data_modify(
  efc,
  c12hour_c = center(c12hour),
  c12hour_z = as_expr(stand)
)
head(new_efc)

# attributes - in this case, value and variable labels - are preserved
str(new_efc)

# using `paste()` to build a string-expression
to_standardize <- c("Petal.Length", "Sepal.Length")
out <- data_modify(
  iris,
  as_expr(
    paste0(to_standardize, "_stand = standardize(", to_standardize, ")")
  )
)
head(out)

# overwrite existing variable, remove old variable
out <- data_modify(iris, Petal.Length = 1 / Sepal.Length, Sepal.Length = NULL)
head(out)

# works on grouped data
grouped_efc <- data_group(efc, "c172code")
new_efc <- data_modify(
  grouped_efc,
  c12hour_c = center(c12hour),
  c12hour_z = c12hour_c / sd(c12hour, na.rm = TRUE),
  c12hour_z2 = standardize(c12hour),
  id = 1:n()
)
head(new_efc)

# works from inside functions
foo1 <- function(data, ...) {
  head(data_modify(data, ...))
}
foo1(iris, SW_fraction = Sepal.Width / 10)
# or
foo1(iris, as_expr("SW_fraction = Sepal.Width / 10"))

# also with string arguments, using `as_expr()`
foo2 <- function(data, modification) {
  head(data_modify(data, as_expr(modification)))
}
foo2(iris, "SW_fraction = Sepal.Width / 10")

# modify at specific positions or if condition is met
d <- iris[1:5, ]
data_modify(d, .at = "Species", .modify = as.numeric)
data_modify(d, .if = is.factor, .modify = as.numeric)

# can be combined with dots
data_modify(d, new_length = Petal.Length * 2, .at = "Species", .modify = as.numeric)

# new variables used in `.at` or `.if`
data_modify(
  d,
  new_length = Petal.Length * 2,
  .at = c("Petal.Length", "new_length"),
  .modify = round
)

# combine "extract_column_names()" and ".at" argument
out <- data_modify(
  d,
  .at = extract_column_names(d, select = starts_with("Sepal")),
  .modify = as.factor
)
# "Sepal.Length" and "Sepal.Width" are now factors
str(out)

}
