Skip to content

Commit

Permalink
Merge pull request #35 from tidymodels/document-functions
Browse files Browse the repository at this point in the history
Document functions
  • Loading branch information
EmilHvitfeldt authored Jul 25, 2024
2 parents 641868e + 5bae8ff commit 2239f9b
Show file tree
Hide file tree
Showing 27 changed files with 333 additions and 92 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
.quarto
derby.log
docs
inst/doc
10 changes: 7 additions & 3 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,27 @@ Imports:
rlang
Suggests:
arrow,
embed,
dbplyr,
dtplyr,
embed,
hardhat,
jsonlite,
kknn,
knitr,
parsnip,
R6,
recipes,
rmarkdown,
rstanarm,
sparklyr,
testthat (>= 3.0.0),
tidypredict,
themis,
tidypredict,
workflows
VignetteBuilder:
knitr
Config/Needs/website: tidyverse/tidytemplate, rmarkdown
Config/testthat/edition: 3
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.2
Config/Needs/website: tidyverse/tidytemplate, rmarkdown
2 changes: 1 addition & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,5 @@ export(orbital_dt)
export(orbital_inline)
export(orbital_json_read)
export(orbital_json_write)
export(orbital_r_fun)
export(orbital_sql)
export(to_r_fun)
11 changes: 10 additions & 1 deletion R/dt.R
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
#' Convert to data.table code
#'
#' @param x A orbital object.
#' Returns [data.table](https://rdatatable.gitlab.io/data.table/) code that
#' is equivilant to prediction code.
#'
#' @param x An [orbital] object.
#'
#' This function requires [dtplyr](https://dtplyr.tidyverse.org/) to be
#' installed to run. The resulting code will likely need to be adopted to your
#' use-case. Most likely by removing the initial `copy(data-name)` at the start.
#'
#' @returns data.table code.
#'
Expand All @@ -24,6 +31,8 @@
#' orbital_dt(orbital_obj)
#' @export
orbital_dt <- function(x) {
rlang::check_installed("dtplyr")

dt <- dtplyr::lazy_dt(data.frame())

res <- dplyr::mutate(dt, !!!orbital_inline(x))
Expand Down
19 changes: 15 additions & 4 deletions R/inline.R
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
#' Use orbital object splicing function
#' Convert orbital objects to quosures
#'
#' @param x A orbital object.
#' Use orbital object splicing function to apply orbital prediction in a quosure
#' aware function such as [dplyr::mutate()].
#'
#' @param x An [orbital] object.
#'
#' @details
#'
#' This function is mostly going to be used for
#' [Dots Injection](https://rlang.r-lib.org/reference/topic-inject.html#dots-injection).
#' See examples for use cases.
#' This function is used internally in [predict()][predict.orbital_class], but
#' is also exported for user flexibility. Should be used with `!!!` as seen in
#' the examples.
#'
#' Note should be taken that using this function modifies existing variables and
#' creates new variables, unlike [predict()][predict.orbital_class] which only
#' returns predictions.
#'
#' @returns a list of quosures.
#' @returns a list of [quosures][rlang::quos].
#'
#' @examplesIf rlang::is_installed(c("recipes", "tidypredict", "workflows"))
#' library(workflows)
Expand All @@ -26,6 +35,8 @@
#'
#' orbital_obj <- orbital(wf_fit)
#'
#' orbital_inline(orbital_obj)
#'
#' library(dplyr)
#'
#' mtcars %>%
Expand Down
24 changes: 20 additions & 4 deletions R/json.R
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
#' Save as json file
#' Save orbital object as json file
#'
#' @param x A orbital object.
#' Saving an orbital object to disk in a human and machine readable way.
#'
#' @param x An [orbital] object.
#' @param path file on disk.
#'
#' @returns nothing.
#' @details
#' The structure of the resulting JSON file allows for easy reading, both by
#' orbital itself with [orbital_json_read()], but potentially by other packages
#' and langauges. The file is versioned by the `version` field to allow for
#' changes why being backwards combatible with older file versions.
#'
#' @returns Nothing.
#'
#' @seealso [orbital_json_read()]
#'
Expand Down Expand Up @@ -40,9 +48,15 @@ orbital_json_write <- function(x, path) {

#' Read orbital json file
#'
#' Reading an orbital object from disk
#'
#' @param path file on disk.
#'
#' @returns A orbital object
#' @details
#' This function is aware of the `version` field of the orbital object, and will
#' read it in correctly, according to its specification.
#'
#' @returns An [orbital] object.
#'
#' @seealso [orbital_json_write()]
#'
Expand All @@ -69,6 +83,8 @@ orbital_json_write <- function(x, path) {
#' orbital_json_read(tmp_file)
#' @export
orbital_json_read <- function(path) {
rlang::check_installed("jsonlite")

res <- jsonlite::read_json(path)

res <- unlist(res$actions)
Expand Down
69 changes: 59 additions & 10 deletions R/orbital.R
Original file line number Diff line number Diff line change
@@ -1,9 +1,33 @@
#' Turn tidymodels workflows into equations
#' Turn tidymodels objects into orbital objects
#'
#' @param x A workflow object.
#' Fitted workflows, parsnip objects, and recipes objects can be turned into an
#' orbital object that contain all the information needed to perform
#' predictions.
#'
#' @param x A fitted workflow, parsnip, or recipes object.
#' @param ... Not currently used.
#'
#' @returns A orbital object.
#' @returns An [orbital] object.
#'
#' @details
#' An orbital object contains all the information that is needed to perform
#' predictions. This makes the objects substantially smaller than the original
#' objects. The main downside with this object is that all the input checking
#' has been removed, and it is thus up to the user to make sure the data is
#' correct.
#'
#' The printing of orbital objects reduce the number of significant digits for
#' easy viewing, the can be changes by using the `digits` argument of `print()`
#' like so `print(orbital_object, digits = 10)`. The printing likewise truncates
#' each equation to fit on one line. This can be turned off using the `truncate`
#' argument like so `print(orbital_object, truncate = FALSE)`.
#'
#' Full list of supported models and recipes steps can be found here:
#' `vignette("supported-models")`.
#'
#' These objects will not be useful by themselves. They can be used to
#' [predict()][predict.orbital_class] with, or to generate code using functions
#' such as [orbital_sql()] or [orbital_dt()].
#'
#' @examplesIf rlang::is_installed(c("recipes", "tidypredict", "workflows"))
#' library(workflows)
Expand All @@ -21,6 +45,14 @@
#'
#' orbital(wf_fit)
#'
#' # Also works on parsnip object by itself
#' fit(lm_spec, mpg ~ disp, data = mtcars) %>%
#' orbital()
#'
#' # And prepped recipes
#' prep(rec_spec) %>%
#' orbital()
#'
#' @export
orbital <- function(x, ...) {
UseMethod("orbital")
Expand All @@ -39,17 +71,20 @@ new_orbital_class <- function(x) {
}

#' @export
print.orbital_class <- function(x, ...) {
print.orbital_class <- function(x, ..., digits = 7, truncate = TRUE) {
x <- unclass(x)
x <- pretty_print(x, digits)

eqs <- paste0(names(x), " = ", x)

eqs_lens <- nchar(eqs)
max_width <- cli::console_width() - 9
clipped <- eqs_lens > max_width

eqs[clipped] <- substr(eqs[clipped], 1, max_width)
eqs[clipped] <- paste(eqs[clipped], "...")
if (truncate) {
eqs_lens <- nchar(eqs)
max_width <- cli::console_width() - 9
clipped <- eqs_lens > max_width

eqs[clipped] <- substr(eqs[clipped], 1, max_width)
eqs[clipped] <- paste(eqs[clipped], "...")
}

cli::cli({
cli::cli_h1("orbital Object")
Expand All @@ -60,3 +95,17 @@ print.orbital_class <- function(x, ...) {

invisible(NULL)
}

pretty_print <- function(x, digits = 7) {
old_values <- regmatches(x, gregexpr( "[0-9]+\\.?[0-9]+", x))
new_values <- lapply(old_values, function(x) signif(as.numeric(x), digits))

old_values <- unlist(old_values, use.names = FALSE)
new_values <- unlist(new_values, use.names = FALSE)

for (i in seq_along(old_values)) {
x <- gsub(old_values[i], new_values[i], x)
}

x
}
16 changes: 13 additions & 3 deletions R/predict.R
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
#' Prediction using orbital objects
#'
#' @param object A orbital object.
#' @param new_data A data frame to predict with.
#' Running prediction on data frame of remote database table, without needing to
#' load original packages used to fit model.
#'
#' @param object An [orbital] object.
#' @param new_data A data frame or remote database table.
#' @param ... Not currently used.
#'
#' @returns A modified data frame.
#' @details
#' Using this function should give identical results to running `predict()` or
#' `bake()` on the orginal object.
#'
#' The prediction done will only return prediction colunms, a opposed to
#' returning all modified functions as done with [orbital_inline()].
#'
#' @returns A modified data frame or remote database table.
#'
#' @examplesIf rlang::is_installed(c("recipes", "tidypredict", "workflows"))
#' library(workflows)
Expand Down
17 changes: 13 additions & 4 deletions R/to.R → R/r_fun.R
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
#' Turn orbital object into a R function
#'
#' @param x A orbital object.
#' Returns a R file that contains a function that output predictions when
#' applied to data frames.
#'
#' @param x An [orbital] object.
#' @param name Name of created function. Defaults to `"orbital_predict"``.
#' @param file A file name.
#'
#' @returns A orbital object.
#' @details
#' The generated function is only expected to work on data frame objects. The
#' generated function doesn't require the orbital package to be loaded.
#' Depending on what models and steps are used, other packages such as dplyr
#' will need to be loaded as well.
#'
#' @returns Nothing.
#'
#' @examplesIf rlang::is_installed(c("recipes", "tidypredict", "workflows"))
#' library(workflows)
Expand All @@ -24,11 +33,11 @@
#'
#' file_name <- tempfile()
#'
#' to_r_fun(orbital_obj, file = file_name)
#' orbital_r_fun(orbital_obj, file = file_name)
#'
#' readLines(file_name)
#' @export
to_r_fun <- function(x, name = "orbital_predict", file) {
orbital_r_fun <- function(x, name = "orbital_predict", file) {
fun <- c(
paste(name, "<- function(x) {"),
"with(x, {",
Expand Down
8 changes: 7 additions & 1 deletion R/sql.R
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
#' Convert to SQL code
#'
#' @param x A orbital object.
#' Returns SQL code that is equivilant to prediction code.
#'
#' @param x An [orbital] object.
#' @param con A connection object.
#'
#' @details
#' This function requires a database connection object, as the resulting code
#' SQL code can differ depending on the type of database.
#'
#' @returns SQL code.
#'
#' @examplesIf rlang::is_installed(c("dbplyr", "recipes", "tidypredict", "workflows"))
Expand Down
7 changes: 6 additions & 1 deletion README.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,9 @@ and then "predicting" with it using `predict()` to get the same results

```{r}
predict(orbital_obj, as_tibble(mtcars))
```
```

# Supported models and recipes steps

Full list of supported models and recipes steps can be found here:
#' `vignette("supported-models")`.
27 changes: 16 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,17 @@ orbital_obj <- orbital(wf_fit)
orbital_obj
#>
#> ── orbital Object ──────────────────────────────────────────────────────────────
#> • cyl = (cyl - 6.1875) / 1.78592164694654
#> • disp = (disp - 230.721875) / 123.938693831382
#> • hp = (hp - 146.6875) / 68.5628684893206
#> • drat = (drat - 3.5965625) / 0.534678736070971
#> • wt = (wt - 3.21725) / 0.978457442989697
#> • qsec = (qsec - 17.84875) / 1.78694323609684
#> • vs = (vs - 0.4375) / 0.504016128774185
#> • am = (am - 0.40625) / 0.498990917235846
#> • gear = (gear - 3.6875) / 0.737804065256947
#> • carb = (carb - 2.8125) / 1.61519997763185
#> • .pred = 20.090625 + (cyl * -0.199023961804222) + (disp * 1.652752216787 ...
#> • cyl = (cyl - 6.1875) / 1.785922
#> • disp = (disp - 230.7219) / 123.9387
#> • hp = (hp - 146.6875) / 68.56287
#> • drat = (drat - 3.596562) / 0.5346787
#> • wt = (wt - 3.21725) / 0.9784574
#> • qsec = (qsec - 17.84875) / 1.786943
#> • vs = (vs - 0.4375) / 0.5040161
#> • am = (am - 0.40625) / 0.4989909
#> • gear = (gear - 3.6875) / 0.7378041
#> • carb = (carb - 2.8125) / 1.6152
#> • .pred = 20.09062 + (cyl * -0.199024) + (disp * 1.652752) + (hp * -1.472 ...
#> ────────────────────────────────────────────────────────────────────────────────
#> 11 equations in total.
```
Expand All @@ -104,3 +104,8 @@ predict(orbital_obj, as_tibble(mtcars))
#> 10 18.7
#> # ℹ 22 more rows
```

# Supported models and recipes steps

Full list of supported models and recipes steps can be found here: \#
`vignette("supported-models")`.
2 changes: 1 addition & 1 deletion _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ reference:
- orbital_dt
- orbital_inline
- orbital_sql
- to_r_fun
- orbital_r_fun
- title: Read and Write
desc: >
Reading and writing orbital objects to json files for easy storage.
Expand Down
Loading

0 comments on commit 2239f9b

Please sign in to comment.