library(tidymodels)
# Also requires the splines2 package to be installed.
1 Creating the data for the app
The idea is to make a regular grid of values and precompute predictions on a data grid. These values are filtered in the shiny
app, and the decision boundary can be computed using a contour plot.
We’ll use tidymodels. First, let’s load packages and set some options:
Here are some options that I set. The first line is probably the most important.
tidymodels_prefer()
theme_set(theme_bw())
options(pillar.advice = FALSE, pillar.min_title_chars = Inf)
We can simulate data using tidymodels functions from the modeldata
package:
<- expr(-1 - 4 * A - 2 * B - 0.2 * A^2 + 1 * B^2)
f
set.seed(943)
<- sim_logistic(500, f)
sim_tr <- sim_logistic(300, f)
sim_val
print(sim_val, n = 5)
# A tibble: 300 × 3
A B class
<dbl> <dbl> <fct>
1 0.325 -0.398 two
2 -2.69 -0.0649 one
3 0.749 -0.675 two
4 0.259 0.553 two
5 1.37 1.34 two
# ℹ 295 more rows
## Make a data grid and get its ranges
<- 100
size <- seq(-4, 4, length.out = size)
x_seq <- crossing(A = seq(-3, 3, length.out = size), B = x_seq) pred_grid
Let’s try a logistic regression with spline terms for both predictors (equal degrees of freedom):
<- logistic_reg()
model_spec <-
model_rec recipe(class ~ ., data = sim_tr) %>%
step_spline_natural(A, B, deg_free = tune())
<- workflow(model_rec, model_spec) model_wflow
Now we will pre-compute the predictions for each model configuration:
<- tibble(deg_free = 3:8)
param_grid
# This will produce predictions on the grid and save them and the original data
<- function(x) {
get_grid_pred augment(x, new_data = pred_grid)
}
<- control_grid(extract = get_grid_pred)
ctrl
<-
model_res %>%
model_wflow tune_grid(resamples = apparent(sim_tr), grid = param_grid, control = ctrl)
# pull out and format the predictions
<-
predicted_values %>%
model_res collect_extracts() %>%
::select(deg_free, .extracts) %>%
dplyrunnest(.extracts) %>%
::select(-.pred_class, -.pred_two)
dplyr
print(predicted_values, n = 5)
# A tibble: 60,000 × 4
deg_free A B .pred_one
<int> <dbl> <dbl> <dbl>
1 3 -3 -4 1
2 3 -3 -3.92 1
3 3 -3 -3.84 1
4 3 -3 -3.76 1
5 3 -3 -3.68 1
# ℹ 59,995 more rows
The shiny app will not have automatic access to any of the objects in our R workspace. We’ll need to load the data into our shiny
app, so we’ll have to download them when it starts.
To do this, we’ll save the files. Since I’m using a GitHub repository, these will be available online via a URL.
save(sim_val, file = "sim_val.RData")
save(predicted_values, file = "predicted_values.RData")
However, security is important for webR
, and not all programmatic techniques to load/upload data into our app will work. From one of our developers:
Because webR runs in the browser, it’s subject to the browser’s security restrictions. As such, downloading data from cross-origin sources is restricted by the CORS mechanism. The browser will only download data from web servers that permit it to do so by including the relevant HTTP headers in its responses.
This is why using URLs from github.com do not work, but ones from raw.githubusercontent.com can be used. For my repo, we can use something like:
<- "topepo"
user <- "shinylive-in-book-test"
repo <- "predicted_values.RData"
file ::glue("https://raw.githubusercontent.com/{user}/{repo}/main/{file}") glue
That’s how we will upload our data into the app.