diff --git a/.Rbuildignore b/.Rbuildignore index 449c1bfe..c6562c91 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -1,2 +1,7 @@ ^TidyDensity\.Rproj$ ^\.Rproj\.user$ +^LICENSE\.md$ +^README\.Rmd$ +^_pkgdown\.yml$ +^docs$ +^pkgdown$ diff --git a/.gitignore b/.gitignore index 565f2b6a..16add95a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ .Rdata .httr-oauth .DS_Store +docs +inst/doc diff --git a/DESCRIPTION b/DESCRIPTION index 7e1bda31..9f98c3cd 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -5,8 +5,15 @@ Authors@R: person("First", "Last", , "first.last@example.com", role = c("aut", "cre"), comment = c(ORCID = "YOUR-ORCID-ID")) Description: What the package does (one paragraph). -License: `use_mit_license()`, `use_gpl3_license()` or friends to pick a - license +License: MIT + file LICENSE Encoding: UTF-8 Roxygen: list(markdown = TRUE) RoxygenNote: 7.1.2 +Imports: + magrittr, + rlang (>= 0.4.11) +Suggests: + rmarkdown, + knitr, + roxygen2 +VignetteBuilder: knitr diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..31ac5ea0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,2 @@ +YEAR: 2022 +COPYRIGHT HOLDER: Steven Paul Sandeson II, MPH diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 00000000..e2d1ca8e --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +# MIT License + +Copyright (c) 2022 Steven Paul Sandeson II, MPH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/NAMESPACE b/NAMESPACE index 6ae92683..7b518948 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,2 +1,16 @@ # Generated by roxygen2: do not edit by hand +export("%>%") +export(":=") +export(.data) +export(as_label) +export(as_name) +export(enquo) +export(enquos) +importFrom(magrittr,"%>%") +importFrom(rlang,":=") +importFrom(rlang,.data) +importFrom(rlang,as_label) +importFrom(rlang,as_name) +importFrom(rlang,enquo) +importFrom(rlang,enquos) diff --git a/R/utils-pipe.R b/R/utils-pipe.R new file mode 100644 index 00000000..fd0b1d13 --- /dev/null +++ b/R/utils-pipe.R @@ -0,0 +1,14 @@ +#' Pipe operator +#' +#' See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details. +#' +#' @name %>% +#' @rdname pipe +#' @keywords internal +#' @export +#' @importFrom magrittr %>% +#' @usage lhs \%>\% rhs +#' @param lhs A value or the magrittr placeholder. +#' @param rhs A function call using the magrittr semantics. +#' @return The result of calling `rhs(lhs)`. +NULL diff --git a/R/utils-tidy-eval.R b/R/utils-tidy-eval.R new file mode 100644 index 00000000..09c3698c --- /dev/null +++ b/R/utils-tidy-eval.R @@ -0,0 +1,107 @@ +#' Tidy eval helpers +#' +#' @description +#' This page lists the tidy eval tools reexported in this package from +#' rlang. To learn about using tidy eval in scripts and packages at a +#' high level, see the [dplyr programming +#' vignette](https://dplyr.tidyverse.org/articles/programming.html) +#' and the [ggplot2 in packages +#' vignette](https://ggplot2.tidyverse.org/articles/ggplot2-in-packages.html). +#' The [Metaprogramming +#' section](https://adv-r.hadley.nz/metaprogramming.html) of [Advanced +#' R](https://adv-r.hadley.nz) may also be useful for a deeper dive. +#' +#' * The tidy eval operators `{{`, `!!`, and `!!!` are syntactic +#' constructs which are specially interpreted by tidy eval functions. +#' You will mostly need `{{`, as `!!` and `!!!` are more advanced +#' operators which you should not have to use in simple cases. +#' +#' The curly-curly operator `{{` allows you to tunnel data-variables +#' passed from function arguments inside other tidy eval functions. +#' `{{` is designed for individual arguments. To pass multiple +#' arguments contained in dots, use `...` in the normal way. +#' +#' ``` +#' my_function <- function(data, var, ...) { +#' data %>% +#' group_by(...) %>% +#' summarise(mean = mean({{ var }})) +#' } +#' ``` +#' +#' * [enquo()] and [enquos()] delay the execution of one or several +#' function arguments. The former returns a single expression, the +#' latter returns a list of expressions. Once defused, expressions +#' will no longer evaluate on their own. They must be injected back +#' into an evaluation context with `!!` (for a single expression) and +#' `!!!` (for a list of expressions). +#' +#' ``` +#' my_function <- function(data, var, ...) { +#' # Defuse +#' var <- enquo(var) +#' dots <- enquos(...) +#' +#' # Inject +#' data %>% +#' group_by(!!!dots) %>% +#' summarise(mean = mean(!!var)) +#' } +#' ``` +#' +#' In this simple case, the code is equivalent to the usage of `{{` +#' and `...` above. Defusing with `enquo()` or `enquos()` is only +#' needed in more complex cases, for instance if you need to inspect +#' or modify the expressions in some way. +#' +#' * The `.data` pronoun is an object that represents the current +#' slice of data. If you have a variable name in a string, use the +#' `.data` pronoun to subset that variable with `[[`. +#' +#' ``` +#' my_var <- "disp" +#' mtcars %>% summarise(mean = mean(.data[[my_var]])) +#' ``` +#' +#' * Another tidy eval operator is `:=`. It makes it possible to use +#' glue and curly-curly syntax on the LHS of `=`. For technical +#' reasons, the R language doesn't support complex expressions on +#' the left of `=`, so we use `:=` as a workaround. +#' +#' ``` +#' my_function <- function(data, var, suffix = "foo") { +#' # Use `{{` to tunnel function arguments and the usual glue +#' # operator `{` to interpolate plain strings. +#' data %>% +#' summarise("{{ var }}_mean_{suffix}" := mean({{ var }})) +#' } +#' ``` +#' +#' * Many tidy eval functions like `dplyr::mutate()` or +#' `dplyr::summarise()` give an automatic name to unnamed inputs. If +#' you need to create the same sort of automatic names by yourself, +#' use `as_label()`. For instance, the glue-tunnelling syntax above +#' can be reproduced manually with: +#' +#' ``` +#' my_function <- function(data, var, suffix = "foo") { +#' var <- enquo(var) +#' prefix <- as_label(var) +#' data %>% +#' summarise("{prefix}_mean_{suffix}" := mean(!!var)) +#' } +#' ``` +#' +#' Expressions defused with `enquo()` (or tunnelled with `{{`) need +#' not be simple column names, they can be arbitrarily complex. +#' `as_label()` handles those cases gracefully. If your code assumes +#' a simple column name, use `as_name()` instead. This is safer +#' because it throws an error if the input is not a name as expected. +#' +#' @md +#' @name tidyeval +#' @keywords internal +#' @importFrom rlang enquo enquos .data := as_name as_label +#' @aliases enquo enquos .data := as_name as_label +#' @export enquo enquos .data := as_name as_label +NULL diff --git a/README.Rmd b/README.Rmd new file mode 100644 index 00000000..70a28eac --- /dev/null +++ b/README.Rmd @@ -0,0 +1,55 @@ +--- +output: github_document +--- + + + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + fig.path = "man/figures/README-", + out.width = "100%" +) +``` + +# TidyDensity + + + + +The goal of TidyDensity is to ... + +## Installation + +You can install the development version of TidyDensity from [GitHub](https://github.com/) with: + +``` r +# install.packages("devtools") +devtools::install_github("spsanderson/TidyDensity") +``` + +## Example + +This is a basic example which shows you how to solve a common problem: + +```{r example} +library(TidyDensity) +## basic example code +``` + +What is special about using `README.Rmd` instead of just `README.md`? You can include R chunks like so: + +```{r cars} +summary(cars) +``` + +You'll still need to render `README.Rmd` regularly, to keep `README.md` up-to-date. `devtools::build_readme()` is handy for this. You could also use GitHub Actions to re-render `README.Rmd` every time you push. An example workflow can be found here: . + +You can also embed plots, for example: + +```{r pressure, echo = FALSE} +plot(pressure) +``` + +In that case, don't forget to commit and push the resulting figure files, so they display on GitHub and CRAN. diff --git a/README.md b/README.md new file mode 100644 index 00000000..16a392a2 --- /dev/null +++ b/README.md @@ -0,0 +1,55 @@ + + + +# TidyDensity + + + + +The goal of TidyDensity is to … + +## Installation + +You can install the development version of TidyDensity from +[GitHub](https://github.com/) with: + +``` r +# install.packages("devtools") +devtools::install_github("spsanderson/TidyDensity") +``` + +## Example + +This is a basic example which shows you how to solve a common problem: + +``` r +library(TidyDensity) +## basic example code +``` + +What is special about using `README.Rmd` instead of just `README.md`? +You can include R chunks like so: + +``` r +summary(cars) +#> speed dist +#> Min. : 4.0 Min. : 2.00 +#> 1st Qu.:12.0 1st Qu.: 26.00 +#> Median :15.0 Median : 36.00 +#> Mean :15.4 Mean : 42.98 +#> 3rd Qu.:19.0 3rd Qu.: 56.00 +#> Max. :25.0 Max. :120.00 +``` + +You’ll still need to render `README.Rmd` regularly, to keep `README.md` +up-to-date. `devtools::build_readme()` is handy for this. You could also +use GitHub Actions to re-render `README.Rmd` every time you push. An +example workflow can be found here: +. + +You can also embed plots, for example: + + + +In that case, don’t forget to commit and push the resulting figure +files, so they display on GitHub and CRAN. diff --git a/_pkgdown.yml b/_pkgdown.yml new file mode 100644 index 00000000..e951e1c7 --- /dev/null +++ b/_pkgdown.yml @@ -0,0 +1,18 @@ +template: + params: + bootswatch: flatly + #ganalytics: G-3393M45M1X + +navbar: + title: "TidyDensity" + left: + - icon: "fa-home" + href: index.html + - text: "Getting Started" + href: articles/getting-started.html + - text: "Function Reference" + href: reference/index.html + - text: "News" + href: news/index.html + +reference: diff --git a/man/figures/README-pressure-1.png b/man/figures/README-pressure-1.png new file mode 100644 index 00000000..c092055f Binary files /dev/null and b/man/figures/README-pressure-1.png differ diff --git a/man/pipe.Rd b/man/pipe.Rd new file mode 100644 index 00000000..a648c296 --- /dev/null +++ b/man/pipe.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils-pipe.R +\name{\%>\%} +\alias{\%>\%} +\title{Pipe operator} +\usage{ +lhs \%>\% rhs +} +\arguments{ +\item{lhs}{A value or the magrittr placeholder.} + +\item{rhs}{A function call using the magrittr semantics.} +} +\value{ +The result of calling \code{rhs(lhs)}. +} +\description{ +See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details. +} +\keyword{internal} diff --git a/man/tidyeval.Rd b/man/tidyeval.Rd new file mode 100644 index 00000000..1fde2d29 --- /dev/null +++ b/man/tidyeval.Rd @@ -0,0 +1,88 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils-tidy-eval.R +\name{tidyeval} +\alias{tidyeval} +\alias{enquo} +\alias{enquos} +\alias{.data} +\alias{:=} +\alias{as_name} +\alias{as_label} +\title{Tidy eval helpers} +\description{ +This page lists the tidy eval tools reexported in this package from +rlang. To learn about using tidy eval in scripts and packages at a +high level, see the \href{https://dplyr.tidyverse.org/articles/programming.html}{dplyr programming vignette} +and the \href{https://ggplot2.tidyverse.org/articles/ggplot2-in-packages.html}{ggplot2 in packages vignette}. +The \href{https://adv-r.hadley.nz/metaprogramming.html}{Metaprogramming section} of \href{https://adv-r.hadley.nz}{Advanced R} may also be useful for a deeper dive. +\itemize{ +\item The tidy eval operators \verb{\{\{}, \verb{!!}, and \verb{!!!} are syntactic +constructs which are specially interpreted by tidy eval functions. +You will mostly need \verb{\{\{}, as \verb{!!} and \verb{!!!} are more advanced +operators which you should not have to use in simple cases. + +The curly-curly operator \verb{\{\{} allows you to tunnel data-variables +passed from function arguments inside other tidy eval functions. +\verb{\{\{} is designed for individual arguments. To pass multiple +arguments contained in dots, use \code{...} in the normal way.\preformatted{my_function <- function(data, var, ...) \{ + data \%>\% + group_by(...) \%>\% + summarise(mean = mean(\{\{ var \}\})) +\} +} +\item \code{\link[=enquo]{enquo()}} and \code{\link[=enquos]{enquos()}} delay the execution of one or several +function arguments. The former returns a single expression, the +latter returns a list of expressions. Once defused, expressions +will no longer evaluate on their own. They must be injected back +into an evaluation context with \verb{!!} (for a single expression) and +\verb{!!!} (for a list of expressions).\preformatted{my_function <- function(data, var, ...) \{ + # Defuse + var <- enquo(var) + dots <- enquos(...) + + # Inject + data \%>\% + group_by(!!!dots) \%>\% + summarise(mean = mean(!!var)) +\} +} + +In this simple case, the code is equivalent to the usage of \verb{\{\{} +and \code{...} above. Defusing with \code{enquo()} or \code{enquos()} is only +needed in more complex cases, for instance if you need to inspect +or modify the expressions in some way. +\item The \code{.data} pronoun is an object that represents the current +slice of data. If you have a variable name in a string, use the +\code{.data} pronoun to subset that variable with \code{[[}.\preformatted{my_var <- "disp" +mtcars \%>\% summarise(mean = mean(.data[[my_var]])) +} +\item Another tidy eval operator is \verb{:=}. It makes it possible to use +glue and curly-curly syntax on the LHS of \code{=}. For technical +reasons, the R language doesn't support complex expressions on +the left of \code{=}, so we use \verb{:=} as a workaround.\preformatted{my_function <- function(data, var, suffix = "foo") \{ + # Use `\{\{` to tunnel function arguments and the usual glue + # operator `\{` to interpolate plain strings. + data \%>\% + summarise("\{\{ var \}\}_mean_\{suffix\}" := mean(\{\{ var \}\})) +\} +} +\item Many tidy eval functions like \code{dplyr::mutate()} or +\code{dplyr::summarise()} give an automatic name to unnamed inputs. If +you need to create the same sort of automatic names by yourself, +use \code{as_label()}. For instance, the glue-tunnelling syntax above +can be reproduced manually with:\preformatted{my_function <- function(data, var, suffix = "foo") \{ + var <- enquo(var) + prefix <- as_label(var) + data \%>\% + summarise("\{prefix\}_mean_\{suffix\}" := mean(!!var)) +\} +} + +Expressions defused with \code{enquo()} (or tunnelled with \verb{\{\{}) need +not be simple column names, they can be arbitrarily complex. +\code{as_label()} handles those cases gracefully. If your code assumes +a simple column name, use \code{as_name()} instead. This is safer +because it throws an error if the input is not a name as expected. +} +} +\keyword{internal} diff --git a/vignettes/.gitignore b/vignettes/.gitignore new file mode 100644 index 00000000..097b2416 --- /dev/null +++ b/vignettes/.gitignore @@ -0,0 +1,2 @@ +*.html +*.R diff --git a/vignettes/getting-started.Rmd b/vignettes/getting-started.Rmd new file mode 100644 index 00000000..6bd4f05b --- /dev/null +++ b/vignettes/getting-started.Rmd @@ -0,0 +1,19 @@ +--- +title: "Getting Started with TidyDensity" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Getting Started with TidyDensity} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +```{r setup} +library(TidyDensity) +```