diff --git a/NEWS.md b/NEWS.md index 16fc26d..bac6e64 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,13 @@ * `eval_select()` now fails when data has duplicate names and a character vector is provided as input (#346). +* New `args_tidy_select` documentation topic. Use the following tags to document tidyselect arguments in your functions: + + ```r + #' @param ... <[`tidy-select`][tidyselect::args_tidy_select]> *doc* + #' @param sel <[`tidy-select`][tidyselect::args_tidy_select]> *doc* + ``` + * `eval_select()` and `eval_relocate()` gain a new `error_arg` argument that can be specified to throw a better error message when `allow_empty = FALSE` or `allow_rename = FALSE` (@olivroy, #327). * `vars_pull()` now also warns when using `.data` (#335). Please diff --git a/R/doc-tidy-selection.R b/R/doc-tidy-selection.R new file mode 100644 index 0000000..7994b74 --- /dev/null +++ b/R/doc-tidy-selection.R @@ -0,0 +1,35 @@ +#' Argument type: tidy-select +#' +#' @description +#' This page describes the `` argument modifier which indicates +#' the argument supports **tidy selections**. Tidy selection provides a concise +#' dialect of R for selecting variables based on their names or properties. +#' +#' Tidy selection is a variant of tidy evaluation. This means that inside +#' functions tidy-select arguments require special attention, as described in +#' the *Indirection* section below. If you've never heard of tidy evaluation +#' before, start with `vignette("programming")`. +#' +#' +#' # Overview of selection features +#' +#' ```{r, child = "man/rmd/overview.Rmd"} +#' ``` +#' +#' +#' # Indirection +#' +#' There are two main cases: +#' +#' * If you want the user to supply a character vector of column names, use `all_of()` +#' or `any_of()`, depending on whether or not you want unknown variable +#' names to cause an error, e.g. `select(df, all_of(vars))`, +#' `select(df, !any_of(vars))`. +#' +#' * If you want the user to supply a tidyselect specification in +#' a function argument, embrace the function argument, e.g. +#' `select(df, {{ vars }})`. +#' +#' @keywords internal +#' @name args_tidy_select +NULL diff --git a/man/args_tidy_select.Rd b/man/args_tidy_select.Rd new file mode 100644 index 0000000..e2ba64c --- /dev/null +++ b/man/args_tidy_select.Rd @@ -0,0 +1,72 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/doc-tidy-selection.R +\name{args_tidy_select} +\alias{args_tidy_select} +\title{Argument type: tidy-select} +\description{ +This page describes the \verb{} argument modifier which indicates +the argument supports \strong{tidy selections}. Tidy selection provides a concise +dialect of R for selecting variables based on their names or properties. + +Tidy selection is a variant of tidy evaluation. This means that inside +functions, tidy-select arguments require special attention, as described in +the \emph{Indirection} section below. If you've never heard of tidy evaluation +before, start with \code{vignette("programming")}. +} +\section{Overview of selection features}{ +Tidyverse selections implement a dialect of R where operators make +it easy to select variables: +\itemize{ +\item \code{:} for selecting a range of consecutive variables. +\item \code{!} for taking the complement of a set of variables. +\item \code{&} and \code{|} for selecting the intersection or the union of two +sets of variables. +\item \code{c()} for combining selections. +} + +In addition, you can use \strong{selection helpers}. Some helpers select specific +columns: +\itemize{ +\item \code{\link[=everything]{everything()}}: Matches all variables. +\item \code{\link[=last_col]{last_col()}}: Select last variable, possibly with an offset. +} + +Other helpers select variables by matching patterns in their names: +\itemize{ +\item \code{\link[=starts_with]{starts_with()}}: Starts with a prefix. +\item \code{\link[=ends_with]{ends_with()}}: Ends with a suffix. +\item \code{\link[=contains]{contains()}}: Contains a literal string. +\item \code{\link[=matches]{matches()}}: Matches a regular expression. +\item \code{\link[=num_range]{num_range()}}: Matches a numerical range like x01, x02, x03. +} + +Or from variables stored in a character vector: +\itemize{ +\item \code{\link[=all_of]{all_of()}}: Matches variable names in a character vector. All +names must be present, otherwise an out-of-bounds error is +thrown. +\item \code{\link[=any_of]{any_of()}}: Same as \code{all_of()}, except that no error is thrown +for names that don't exist. +} + +Or using a predicate function: +\itemize{ +\item \code{\link[=where]{where()}}: Applies a function to all variables and selects those +for which the function returns \code{TRUE}. +} +} + +\section{Indirection}{ +There are two main cases: +\itemize{ +\item If you have a character vector of column names, use \code{all_of()} +or \code{any_of()}, depending on whether or not you want unknown variable +names to cause an error, e.g. \code{select(df, all_of(vars))}, +\code{select(df, !any_of(vars))}. +\item If you want the user to be able to supply a tidyselect specification in +a function argument, embrace the function argument, e.g. +\code{select(df, {{ vars }})}. +} +} + +\keyword{internal} diff --git a/man/language.Rd b/man/language.Rd index 3723a8e..560e8c9 100644 --- a/man/language.Rd +++ b/man/language.Rd @@ -7,35 +7,46 @@ \description{ \subsection{Overview of selection features:}{ -tidyselect implements a DSL for selecting variables. It provides helpers -for selecting variables: +Tidyverse selections implement a dialect of R where operators make +it easy to select variables: \itemize{ -\item \code{var1:var10}: variables lying between \code{var1} on the left and \code{var10} on the right. +\item \code{:} for selecting a range of consecutive variables. +\item \code{!} for taking the complement of a set of variables. +\item \code{&} and \code{|} for selecting the intersection or the union of two +sets of variables. +\item \code{c()} for combining selections. } + +In addition, you can use \strong{selection helpers}. Some helpers select specific +columns: +\itemize{ +\item \code{\link[=everything]{everything()}}: Matches all variables. +\item \code{\link[=last_col]{last_col()}}: Select last variable, possibly with an offset. +} + +Other helpers select variables by matching patterns in their names: \itemize{ -\item \code{\link[=starts_with]{starts_with("a")}}: names that start with \code{"a"}. -\item \code{\link[=ends_with]{ends_with("z")}}: names that end with \code{"z"}. -\item \code{\link[=contains]{contains("b")}}: names that contain \code{"b"}. -\item \code{\link[=matches]{matches("x.y")}}: names that match regular expression \code{x.y}. -\item \code{\link[=num_range]{num_range(x, 1:4)}}: names following the pattern, \code{x1}, \code{x2}, ..., \code{x4}. -\item \code{\link[=all_of]{all_of(vars)}}/\code{\link[=any_of]{any_of(vars)}}: -matches names stored in the character vector \code{vars}. \code{all_of(vars)} will -error if the variables aren't present; \code{any_of(var)} will match just the -variables that exist. -\item \code{\link[=everything]{everything()}}: all variables. -\item \code{\link[=last_col]{last_col()}}: furthest column on the right. -\item \code{\link[=where]{where(is.numeric)}}: all variables where -\code{is.numeric()} returns \code{TRUE}. +\item \code{\link[=starts_with]{starts_with()}}: Starts with a prefix. +\item \code{\link[=ends_with]{ends_with()}}: Ends with a suffix. +\item \code{\link[=contains]{contains()}}: Contains a literal string. +\item \code{\link[=matches]{matches()}}: Matches a regular expression. +\item \code{\link[=num_range]{num_range()}}: Matches a numerical range like x01, x02, x03. } -As well as operators for combining those selections: +Or from variables stored in a character vector: \itemize{ -\item \code{!selection}: only variables that don't match \code{selection}. -\item \code{selection1 & selection2}: only variables included in both \code{selection1} and \code{selection2}. -\item \code{selection1 | selection2}: all variables that match either \code{selection1} or \code{selection2}. +\item \code{\link[=all_of]{all_of()}}: Matches variable names in a character vector. All +names must be present, otherwise an out-of-bounds error is +thrown. +\item \code{\link[=any_of]{any_of()}}: Same as \code{all_of()}, except that no error is thrown +for names that don't exist. } -When writing code inside packages you can substitute \code{"var"} for \code{var} to avoid \verb{R CMD check} notes. +Or using a predicate function: +\itemize{ +\item \code{\link[=where]{where()}}: Applies a function to all variables and selects those +for which the function returns \code{TRUE}. +} } } \section{Simple examples}{ diff --git a/man/rmd/overview.Rmd b/man/rmd/overview.Rmd index f7af164..e78a070 100644 --- a/man/rmd/overview.Rmd +++ b/man/rmd/overview.Rmd @@ -1,26 +1,35 @@ +Tidyverse selections implement a dialect of R where operators make +it easy to select variables: -tidyselect implements a DSL for selecting variables. It provides helpers -for selecting variables: - -- `var1:var10`: variables lying between `var1` on the left and `var10` on the right. -* [`starts_with("a")`][tidyselect::starts_with]: names that start with `"a"`. -* [`ends_with("z")`][tidyselect::ends_with]: names that end with `"z"`. -* [`contains("b")`][tidyselect::contains]: names that contain `"b"`. -* [`matches("x.y")`][tidyselect::matches]: names that match regular expression `x.y`. -* [`num_range(x, 1:4)`][tidyselect::num_range]: names following the pattern, `x1`, `x2`, ..., `x4`. -* [`all_of(vars)`][tidyselect::all_of]/[`any_of(vars)`][tidyselect::any_of()]: - matches names stored in the character vector `vars`. `all_of(vars)` will - error if the variables aren't present; `any_of(var)` will match just the - variables that exist. -* [`everything()`][tidyselect::everything]: all variables. -* [`last_col()`][tidyselect::last_col]: furthest column on the right. -* [`where(is.numeric)`][tidyselect::where]: all variables where - `is.numeric()` returns `TRUE`. - -As well as operators for combining those selections: - -- `!selection`: only variables that don't match `selection`. -- `selection1 & selection2`: only variables included in both `selection1` and `selection2`. -- `selection1 | selection2`: all variables that match either `selection1` or `selection2`. - -When writing code inside packages you can substitute `"var"` for `var` to avoid `R CMD check` notes. +- `:` for selecting a range of consecutive variables. +- `!` for taking the complement of a set of variables. +- `&` and `|` for selecting the intersection or the union of two + sets of variables. +- `c()` for combining selections. + +In addition, you can use __selection helpers__. Some helpers select specific +columns: + +* [`everything()`][tidyselect::everything]: Matches all variables. +* [`last_col()`][tidyselect::last_col]: Select last variable, possibly with an offset. + +Other helpers select variables by matching patterns in their names: + +* [`starts_with()`][tidyselect::starts_with]: Starts with a prefix. +* [`ends_with()`][tidyselect::ends_with()]: Ends with a suffix. +* [`contains()`][tidyselect::contains()]: Contains a literal string. +* [`matches()`][tidyselect::matches()]: Matches a regular expression. +* [`num_range()`][tidyselect::num_range()]: Matches a numerical range like x01, x02, x03. + +Or from external variables stored in a character vector: + +* [`all_of()`][tidyselect::all_of()]: Matches variable names in a character vector. All + names must be present, otherwise an out-of-bounds error is + thrown. +* [`any_of()`][tidyselect::any_of()]: Same as `all_of()`, except that no error is thrown + for names that don't exist. + +Or using a predicate function: + +* [`where()`][tidyselect::where()]: Applies a function to all variables and selects those + for which the function returns `TRUE`.