From 2acec481126a21b57f179d7556b01b34af1e3cbe Mon Sep 17 00:00:00 2001
From: Anthony Flores <70184250+AnthonyOKC@users.noreply.github.com>
Date: Sun, 1 Oct 2023 18:28:54 -0500
Subject: [PATCH] Add, style, and roxygenise functions
---
.Rprofile | 1 +
NAMESPACE | 104 +-
R/covid_eviction_labels.R | 80 +-
R/custom_ojo_theme.R | 45 +-
R/hc_theme_ojo.R | 57 +-
R/highchart_label_formatter.R | 83 +-
R/ojo_add_geoid.R | 105 +-
R/ojo_add_geometries.R | 39 +-
R/ojo_add_month_and_year.R | 30 +-
R/ojo_add_population.R | 238 +--
R/ojo_aggregate.R | 177 ++-
R/ojo_district_and_date_filters.R | 52 +-
R/ojo_highchart_map.R | 158 +-
R/ojo_optional_filter.R | 29 +-
R/ojo_plot_lines.R | 158 +-
R/pretty_variable_names.R | 42 +-
R/tably.R | 63 +-
_sinewconfig.yml | 2 +
man/covid_eviction_labels.Rd | 38 +
man/custom_ojo_theme.Rd | 30 +
man/hc_theme_ojo.Rd | 31 +
man/hello.Rd | 20 -
man/highchart_label_formatter.Rd | 51 +
man/ojo_add_geoid.Rd | 40 +
man/ojo_add_geometries.Rd | 39 +
man/ojo_add_month_and_year.Rd | 38 +
man/ojo_add_population.Rd | 51 +
man/ojo_aggregate.Rd | 52 +
man/ojo_district_and_date_filters.Rd | 50 +
man/ojo_highchart_map.Rd | 58 +
man/ojo_optional_filter.Rd | 37 +
man/ojo_plot_lines.Rd | 78 +
man/plumber_api.Rd | 18 -
man/pretty_variable_names.Rd | 34 +
man/shiny_app.Rd | 15 -
man/tably.Rd | 42 +
renv.lock | 2173 ++++++++++++++++++++++++++
renv/.gitignore | 7 +
renv/activate.R | 1181 ++++++++++++++
renv/settings.json | 19 +
40 files changed, 5001 insertions(+), 564 deletions(-)
create mode 100644 .Rprofile
create mode 100644 _sinewconfig.yml
create mode 100644 man/covid_eviction_labels.Rd
create mode 100644 man/custom_ojo_theme.Rd
create mode 100644 man/hc_theme_ojo.Rd
delete mode 100644 man/hello.Rd
create mode 100644 man/highchart_label_formatter.Rd
create mode 100644 man/ojo_add_geoid.Rd
create mode 100644 man/ojo_add_geometries.Rd
create mode 100644 man/ojo_add_month_and_year.Rd
create mode 100644 man/ojo_add_population.Rd
create mode 100644 man/ojo_aggregate.Rd
create mode 100644 man/ojo_district_and_date_filters.Rd
create mode 100644 man/ojo_highchart_map.Rd
create mode 100644 man/ojo_optional_filter.Rd
create mode 100644 man/ojo_plot_lines.Rd
delete mode 100644 man/plumber_api.Rd
create mode 100644 man/pretty_variable_names.Rd
delete mode 100644 man/shiny_app.Rd
create mode 100644 man/tably.Rd
create mode 100644 renv.lock
create mode 100644 renv/.gitignore
create mode 100644 renv/activate.R
create mode 100644 renv/settings.json
diff --git a/.Rprofile b/.Rprofile
new file mode 100644
index 0000000..81b960f
--- /dev/null
+++ b/.Rprofile
@@ -0,0 +1 @@
+source("renv/activate.R")
diff --git a/NAMESPACE b/NAMESPACE
index 62a3c9a..d5a0cb9 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -1,6 +1,102 @@
# Generated by roxygen2: do not edit by hand
-export(hello)
-export(plumber_api)
-export(shiny_app)
-importFrom(utils,packageName)
+export(covid_eviction_labels)
+export(custom_ojo_theme)
+export(hc_theme_ojo)
+export(highchart_label_formatter)
+export(ojo_add_geoid)
+export(ojo_add_geometries)
+export(ojo_add_month_and_year)
+export(ojo_add_population)
+export(ojo_aggregate)
+export(ojo_district_and_date_filters)
+export(ojo_highchart_map)
+export(ojo_optional_filter)
+export(ojo_plot_lines)
+export(pretty_variable_names)
+export(tably)
+importFrom(dplyr,any_of)
+importFrom(dplyr,arrange)
+importFrom(dplyr,bind_rows)
+importFrom(dplyr,count)
+importFrom(dplyr,cross_join)
+importFrom(dplyr,distinct)
+importFrom(dplyr,filter)
+importFrom(dplyr,if_else)
+importFrom(dplyr,join_by)
+importFrom(dplyr,left_join)
+importFrom(dplyr,matches)
+importFrom(dplyr,mutate)
+importFrom(dplyr,nth)
+importFrom(dplyr,pull)
+importFrom(dplyr,select)
+importFrom(dplyr,slice)
+importFrom(dplyr,starts_with)
+importFrom(dplyr,summarise)
+importFrom(dplyr,tibble)
+importFrom(geojsonsf,sf_geojson)
+importFrom(ggplot2,aes)
+importFrom(ggplot2,annotate)
+importFrom(ggplot2,as_labeller)
+importFrom(ggplot2,element_blank)
+importFrom(ggplot2,element_rect)
+importFrom(ggplot2,element_text)
+importFrom(ggplot2,facet_wrap)
+importFrom(ggplot2,geom_label)
+importFrom(ggplot2,geom_line)
+importFrom(ggplot2,geom_point)
+importFrom(ggplot2,geom_rect)
+importFrom(ggplot2,geom_vline)
+importFrom(ggplot2,ggplot)
+importFrom(ggplot2,guide_legend)
+importFrom(ggplot2,guides)
+importFrom(ggplot2,scale_color_manual)
+importFrom(ggplot2,scale_fill_manual)
+importFrom(ggplot2,scale_y_continuous)
+importFrom(ggplot2,theme)
+importFrom(ggplot2,theme_bw)
+importFrom(ggplot2,vars)
+importFrom(grDevices,nclass.FD)
+importFrom(graphics,hist)
+importFrom(highcharter,color_classes)
+importFrom(highcharter,color_stops)
+importFrom(highcharter,hc_add_series_map)
+importFrom(highcharter,hc_add_theme)
+importFrom(highcharter,hc_caption)
+importFrom(highcharter,hc_colorAxis)
+importFrom(highcharter,hc_legend)
+importFrom(highcharter,hc_mapNavigation)
+importFrom(highcharter,hc_theme)
+importFrom(highcharter,hc_theme_merge)
+importFrom(highcharter,hc_theme_smpl)
+importFrom(highcharter,highchart)
+importFrom(htmlwidgets,JS)
+importFrom(jsonlite,fromJSON)
+importFrom(lubridate,floor_date)
+importFrom(lubridate,year)
+importFrom(lubridate,ymd)
+importFrom(ojodb,ojo_pal)
+importFrom(purrr,map_chr)
+importFrom(rlang,as_label)
+importFrom(rlang,check_installed)
+importFrom(rlang,enquo)
+importFrom(rlang,enquos)
+importFrom(rlang,quo_get_expr)
+importFrom(rlang,quo_text)
+importFrom(rlang,quos)
+importFrom(rlang,sym)
+importFrom(scales,label_comma)
+importFrom(snakecase,to_title_case)
+importFrom(stats,filter)
+importFrom(stats,na.omit)
+importFrom(stringr,str_detect)
+importFrom(stringr,str_flatten)
+importFrom(stringr,str_remove)
+importFrom(stringr,str_replace_all)
+importFrom(stringr,str_to_upper)
+importFrom(tidycensus,get_estimates)
+importFrom(tidyr,pivot_longer)
+importFrom(tidyr,pivot_wider)
+importFrom(tigris,counties)
+importFrom(tigris,states)
+importFrom(viridis,magma)
diff --git a/R/covid_eviction_labels.R b/R/covid_eviction_labels.R
index 3866cfb..d2eb69f 100644
--- a/R/covid_eviction_labels.R
+++ b/R/covid_eviction_labels.R
@@ -1,100 +1,120 @@
+#' @title FUNCTION_TITLE
+#' @description FUNCTION_DESCRIPTION
+#' @param label_data PARAM_DESCRIPTION
+#' @param ... PARAM_DESCRIPTION
+#' @param .labels PARAM_DESCRIPTION, Default: FALSE
+#' @return OUTPUT_DESCRIPTION
+#' @details DETAILS
+#' @examples
+#' \dontrun{
+#' if(interactive()){
+#' #EXAMPLE1
+#' }
+#' }
+#' @seealso
+#' \code{\link[ggplot2]{geom_label}}, \code{\link[ggplot2]{aes}}, \code{\link[ggplot2]{annotate}}, \code{\link[ggplot2]{geom_raster}}, \code{\link[ggplot2]{scale_manual}}, \code{\link[ggplot2]{guide_legend}}, \code{\link[ggplot2]{geom_abline}}
+#' \code{\link[lubridate]{ymd}}
+#' @rdname covid_eviction_labels
+#' @export
+#' @author Anthony Flores
+#' @importFrom ggplot2 geom_label aes annotate geom_rect scale_fill_manual guide_legend geom_vline
+#' @importFrom lubridate ymd
covid_eviction_labels <- function(label_data, ..., .labels = FALSE) {
-
ojo_labels <- function(.label, data = label_data, .x, .y) {
"Helper: Makes it more efficient to make and edit the aesthetics of all labels at once."
- geom_label(
+ ggplot2::geom_label(
data = data,
label = .label,
- aes(x = {{.x}}, y = {{.y}}, group = variable),
+ ggplot2::aes(x = {{ .x }}, y = {{ .y }}, group = variable),
fontface = "bold", size = 2.5, hjust = -0.02,
label.size = 0, fill = "#dddddd", color = "#231f20"
- )
+ )
}
# Dates of events are rounded to nearest month for readability
# COVID State of Emergency Declared
- date_covid <- ymd("2020-03-01")
+ date_covid <- lubridate::ymd("2020-03-01")
# Federal Eviction Moratorium Begins (CARES Act passed 3-24-2020)
- date_federalMoratoriumBegins <- ymd("2020-04-01")
+ date_federalMoratoriumBegins <- lubridate::ymd("2020-04-01")
# Federal Eviction Moratorium Expires 7/25/2020
- date_federalMoratoriumExpires <- ymd("2020-08-01")
+ date_federalMoratoriumExpires <- lubridate::ymd("2020-08-01")
# CDC Moratorium Begins 9/4/2020
- date_cdcMoratoriumBegins <- ymd("2020-09-01")
+ date_cdcMoratoriumBegins <- lubridate::ymd("2020-09-01")
# CDC Moratorium Expires 7/31/2021
- date_cdcMoratoriumEnds <- ymd("2021-08-01")
+ date_cdcMoratoriumEnds <- lubridate::ymd("2021-08-01")
components <- list(
# Highlight dates where there is an active eviction moratorium or court closure.
- annotate(
+ ggplot2::annotate(
"rect",
- xmin = date_covid, xmax = date_federalMoratoriumExpires,
- ymin = -Inf, ymax = Inf,
+ xmin = date_covid, xmax = date_federalMoratoriumExpires,
+ ymin = -Inf, ymax = Inf,
fill = "#000000", alpha = 0.25,
color = NA
),
- annotate(
+ ggplot2::annotate(
"rect",
- xmin = date_cdcMoratoriumBegins, xmax = date_cdcMoratoriumEnds,
- ymin = -Inf, ymax = Inf,
+ xmin = date_cdcMoratoriumBegins, xmax = date_cdcMoratoriumEnds,
+ ymin = -Inf, ymax = Inf,
fill = "#000000", alpha = 0.25,
color = NA
),
# We use this to make the legend (the x & y values don't matter)
- geom_rect(
- aes(
+ ggplot2::geom_rect(
+ ggplot2::aes(
xmin = date_covid, xmax = date_federalMoratoriumBegins,
ymin = 0, ymax = Inf,
fill = "Active Eviction Moratorium\nor Court Closure",
color = NULL
)
),
- scale_fill_manual(
+ ggplot2::scale_fill_manual(
name = "",
values = c("Active Eviction Moratorium\nor Court Closure" = "#00000000"),
- guide = guide_legend(override.aes = list(fill = "#000000", alpha = .2))
+ guide = ggplot2::guide_legend(override.aes = list(fill = "#000000", alpha = .2))
)
)
if (.labels == TRUE) {
components <- append(components, list(
- geom_vline(xintercept = date_covid, linetype = "dashed"),
- geom_vline(xintercept = date_federalMoratoriumBegins, linetype = "dashed"),
- geom_vline(xintercept = date_federalMoratoriumExpires, linetype = "dashed"),
- geom_vline(xintercept = date_cdcMoratoriumBegins, linetype = "dashed"),
- geom_vline(xintercept = date_cdcMoratoriumEnds, linetype = "dashed"),
+ ggplot2::geom_vline(xintercept = date_covid, linetype = "dashed"),
+ ggplot2::geom_vline(xintercept = date_federalMoratoriumBegins, linetype = "dashed"),
+ ggplot2::geom_vline(xintercept = date_federalMoratoriumExpires, linetype = "dashed"),
+ ggplot2::geom_vline(xintercept = date_cdcMoratoriumBegins, linetype = "dashed"),
+ ggplot2::geom_vline(xintercept = date_cdcMoratoriumEnds, linetype = "dashed"),
ojo_labels(
data = label_data,
.label = "COVID State of Emergency:\nCourt Closes Temporarily",
.x = date_covid,
.y = maxValue * .95
- ),
+ ),
ojo_labels(
data = label_data,
.label = "CARES Act: Federal Eviction Moratorium Issued",
.x = date_federalMoratoriumBegins,
.y = maxValue * .8
- ),
+ ),
ojo_labels(
data = label_data,
.label = "Federal Eviction\nMoratorium Expires",
.x = date_federalMoratoriumExpires,
.y = maxValue * .7
- ),
+ ),
ojo_labels(
data = label_data,
.label = "CDC Eviction\nMoratorium Issued",
.x = date_cdcMoratoriumBegins,
.y = maxValue * .2
- ),
+ ),
ojo_labels(
data = label_data,
.label = "CDC Eviction\nMoratorium Expires",
.x = date_cdcMoratoriumEnds,
.y = maxValue * .95
- )
- ))
+ )
+ ))
}
diff --git a/R/custom_ojo_theme.R b/R/custom_ojo_theme.R
index 002211c..49f9147 100644
--- a/R/custom_ojo_theme.R
+++ b/R/custom_ojo_theme.R
@@ -1,20 +1,37 @@
+#' @title FUNCTION_TITLE
+#' @description FUNCTION_DESCRIPTION
+
+#' @return OUTPUT_DESCRIPTION
+#' @details DETAILS
+#' @examples
+#' \dontrun{
+#' if(interactive()){
+#' #EXAMPLE1
+#' }
+#' }
+#' @seealso
+#' \code{\link[ggplot2]{ggtheme}}, \code{\link[ggplot2]{theme}}, \code{\link[ggplot2]{margin}}
+#' @rdname custom_ojo_theme
+#' @export
+#' @author Anthony Flores
+#' @importFrom ggplot2 theme_bw theme element_blank element_rect element_text
custom_ojo_theme <- function() {
ggplot2::theme_bw(
base_size = 16,
base_family = "roboto_condensed"
) %+replace%
- ggplot2::theme(
- panel.background = ggplot2::element_blank(),
- plot.background = ggplot2::element_blank(),
- legend.background = ggplot2::element_rect(fill = "transparent", colour = NA),
- legend.key = ggplot2::element_rect(fill = "transparent", colour = NA),
- legend.position = "top"
- ) +
- theme(
- legend.title = element_blank(),
- legend.text = element_text(size = 14),
- axis.title = element_blank(),
- strip.background = element_blank(),
- strip.text = element_text(face = "bold")
- )
+ ggplot2::theme(
+ panel.background = ggplot2::element_blank(),
+ plot.background = ggplot2::element_blank(),
+ legend.background = ggplot2::element_rect(fill = "transparent", colour = NA),
+ legend.key = ggplot2::element_rect(fill = "transparent", colour = NA),
+ legend.position = "top"
+ ) +
+ ggplot2::theme(
+ legend.title = ggplot2::element_blank(),
+ legend.text = ggplot2::element_text(size = 14),
+ axis.title = ggplot2::element_blank(),
+ strip.background = ggplot2::element_blank(),
+ strip.text = ggplot2::element_text(face = "bold")
+ )
}
diff --git a/R/hc_theme_ojo.R b/R/hc_theme_ojo.R
index a9ee914..5320383 100644
--- a/R/hc_theme_ojo.R
+++ b/R/hc_theme_ojo.R
@@ -1,22 +1,43 @@
-library(highcharter)
-library(ojodb)
-hc_theme_ojo <- hc_theme_merge(
- hc_theme_smpl(),
- hc_theme(
- colors = ojo_pal,
- plotOptions = list(
- line = list(
- lineWidth = 3,
- marker = list(
- enabled = TRUE,
- lineColor = "#000000",
- lineWidth = 1.5
+#' @title FUNCTION_TITLE
+#' @description FUNCTION_DESCRIPTION
+
+#' @return OUTPUT_DESCRIPTION
+#' @details DETAILS
+#' @examples
+#' \dontrun{
+#' if(interactive()){
+#' #EXAMPLE1
+#' }
+#' }
+#' @seealso
+#' \code{\link[highcharter]{hc_theme_merge}}, \code{\link[highcharter]{hc_theme_smpl}}, \code{\link[highcharter]{hc_theme}}
+#' \code{\link[ojodb]{ojo_pal}}
+#' @rdname hc_theme_ojo
+#' @export
+#' @author Anthony Flores
+#' @importFrom highcharter hc_theme_merge hc_theme_smpl hc_theme
+#' @importFrom ojodb ojo_pal
+hc_theme_ojo <- function() {
+ theme <- highcharter::hc_theme_merge(
+ highcharter::hc_theme_smpl(),
+ highcharter::hc_theme(
+ colors = ojodb::ojo_pal,
+ plotOptions = list(
+ line = list(
+ lineWidth = 3,
+ marker = list(
+ enabled = TRUE,
+ lineColor = "#000000",
+ lineWidth = 1.5
+ )
)
+ ),
+ legend = list(
+ align = "center",
+ verticalAlign = "top"
)
- ),
- legend = list(
- align = "center",
- verticalAlign = "top"
)
)
-)
+
+ return(theme)
+}
diff --git a/R/highchart_label_formatter.R b/R/highchart_label_formatter.R
index bb92f3d..21eff68 100644
--- a/R/highchart_label_formatter.R
+++ b/R/highchart_label_formatter.R
@@ -1,44 +1,65 @@
+#' @title FUNCTION_TITLE
+#' @description FUNCTION_DESCRIPTION
+#' @param variable_name PARAM_DESCRIPTION
+#' @param prefix PARAM_DESCRIPTION, Default: ''
+#' @param suffix PARAM_DESCRIPTION, Default: ''
+#' @param value_identifier PARAM_DESCRIPTION, Default: 'this.value'
+#' @param digits PARAM_DESCRIPTION, Default: 0
+#' @param dataClass PARAM_DESCRIPTION, Default: FALSE
+#' @return OUTPUT_DESCRIPTION
+#' @details DETAILS
+#' @examples
+#' \dontrun{
+#' if(interactive()){
+#' #EXAMPLE1
+#' }
+#' }
+#' @seealso
+#' \code{\link[stringr]{str_detect}}, \code{\link[stringr]{str_replace}}
+#' \code{\link[htmlwidgets]{JS}}
+#' @rdname highchart_label_formatter
+#' @export
+#' @author Anthony Flores
+#' @importFrom stringr str_detect str_replace_all
+#' @importFrom htmlwidgets JS
highchart_label_formatter <- function(variable_name,
prefix = "",
suffix = "",
value_identifier = "this.value",
digits = 0,
- dataClass = FALSE
- ) {
+ dataClass = FALSE) {
+ if (stringr::str_detect(variable_name, "[P|p]ercent")) {
+ formatted_value <- "Highcharts.numberFormat(this.value * 100, 0) + '%'"
+ } else if (stringr::str_detect(variable_name, "[I|i]ncome|[A|a]mount")) {
+ formatted_value <- "'$' + Highcharts.numberFormat(this.value, 0)"
+ } else {
+ formatted_value <- "Highcharts.numberFormat(this.value, 0)"
+ }
- if (str_detect(variable_name, "[P|p]ercent")) {
- formatted_value <- "Highcharts.numberFormat(this.value * 100, 0) + '%'"
- } else if (str_detect(variable_name, "[I|i]ncome|[A|a]mount")) {
- formatted_value <- "'$' + Highcharts.numberFormat(this.value, 0)"
- } else {
- formatted_value <- "Highcharts.numberFormat(this.value, 0)"
- }
+ if (value_identifier != "this.value") {
+ formatted_value <-
+ stringr::str_replace_all(formatted_value, "this.value", value_identifier)
+ }
- if (value_identifier != "this.value") {
- formatted_value <-
- str_replace_all(formatted_value, "this.value", value_identifier)
- }
+ if (digits != 0) {
+ formatted_value <-
+ stringr::str_replace_all(formatted_value, "0\\)", paste0(digits, "\\)"))
+ }
- if (digits != 0) {
- formatted_value <-
- str_replace_all(formatted_value, "0\\)", paste0(digits, "\\)"))
- }
+ if (dataClass == TRUE) {
+ modified_from <- stringr::str_replace_all(formatted_value, "this.value", "this.from")
+ modified_to <- stringr::str_replace_all(formatted_value, "this.value", "this.to")
- if (dataClass == TRUE) {
- modified_from <- str_replace_all(formatted_value, "this.value", "this.from")
- modified_to <- str_replace_all(formatted_value, "this.value", "this.to")
-
- return(JS(paste0("function() {
+ return(htmlwidgets::JS(paste0(
+ "function() {
return ", prefix,
- modified_from, " + ' — ' + ", modified_to,
- suffix, ";", "
- }"))
- )
- }
+ modified_from, " + ' — ' + ", modified_to,
+ suffix, ";", "
+ }"
+ )))
+ }
- return(JS(paste0("function() {
+ return(htmlwidgets::JS(paste0("function() {
return ", prefix, formatted_value, suffix, ";", "
- }"))
- )
-
+ }")))
}
diff --git a/R/ojo_add_geoid.R b/R/ojo_add_geoid.R
index dfe2887..4af98cb 100644
--- a/R/ojo_add_geoid.R
+++ b/R/ojo_add_geoid.R
@@ -1,48 +1,71 @@
+#' @title FUNCTION_TITLE
+#' @description FUNCTION_DESCRIPTION
+#' @param data PARAM_DESCRIPTION
+#' @param geography PARAM_DESCRIPTION, Default: c("county", "state")
+#' @param year PARAM_DESCRIPTION, Default: 2019
+#' @return OUTPUT_DESCRIPTION
+#' @details DETAILS
+#' @examples
+#' \dontrun{
+#' if(interactive()){
+#' #EXAMPLE1
+#' }
+#' }
+#' @seealso
+#' \code{\link[rlang]{is_installed}}
+#' \code{\link[tidycensus]{get_estimates}}
+#' \code{\link[dplyr]{mutate}}, \code{\link[dplyr]{select}}, \code{\link[dplyr]{mutate-joins}}
+#' \code{\link[stringr]{str_remove}}, \code{\link[stringr]{case}}, \code{\link[stringr]{str_replace}}
+#' @rdname ojo_add_geoid
+#' @export
+#' @author Anthony Flores
+#' @importFrom rlang check_installed
+#' @importFrom tidycensus get_estimates
+#' @importFrom dplyr mutate select left_join
+#' @importFrom stringr str_remove str_to_upper str_replace_all
ojo_add_geoid <- function(data,
geography = c("county", "state"),
- year = 2019
- ) {
-
- rlang::check_installed(pkg = "tidycensus")
-
- # Variable Handling
- .geography = geography[1]
-
- population_variable <- "POPESTIMATE"
-
- if (year <= 2019) {
- population_variable <- "POP"
- }
-
- df <- tidycensus::get_estimates(
- variables = population_variable,
- geography = .geography,
- year = year,
- state = "OK"
- )
-
- if (.geography == "county") {
- df <-
- df |>
- dplyr::mutate(
- district =
- NAME |>
- stringr::str_remove(" County.*") |>
- stringr::str_to_upper() |>
- str_replace_all("LE FLORE", "LEFLORE")
- ) |>
- dplyr::select(district, GEOID)
-
- data <-
- data |>
- dplyr::left_join(df)
-
- return(data)
- }
+ year = 2019) {
+ rlang::check_installed(pkg = "tidycensus")
+
+ # Variable Handling
+ .geography <- geography[1]
+
+ population_variable <- "POPESTIMATE"
+
+ if (year <= 2019) {
+ population_variable <- "POP"
+ }
+
+ df <- tidycensus::get_estimates(
+ variables = population_variable,
+ geography = .geography,
+ year = year,
+ state = "OK"
+ )
+
+ if (.geography == "county") {
+ df <-
+ df |>
+ dplyr::mutate(
+ district =
+ NAME |>
+ stringr::str_remove(" County.*") |>
+ stringr::str_to_upper() |>
+ stringr::str_replace_all("LE FLORE", "LEFLORE")
+ ) |>
+ dplyr::select(district, GEOID)
data <-
- data |>
- mutate(GEOID = df$GEOID)
+ data |>
+ dplyr::left_join(df)
return(data)
+ }
+
+ data <-
+ data |>
+ dplyr::mutate(GEOID = df$GEOID)
+
+ return(data)
}
diff --git a/R/ojo_add_geometries.R b/R/ojo_add_geometries.R
index 07d2b8a..821e058 100644
--- a/R/ojo_add_geometries.R
+++ b/R/ojo_add_geometries.R
@@ -1,21 +1,42 @@
-library(tigris)
-library(sf)
+#' @title FUNCTION_TITLE
+#' @description FUNCTION_DESCRIPTION
+#' @param data PARAM_DESCRIPTION
+#' @param geography PARAM_DESCRIPTION, Default: c("county", "state")
+#' @param ... PARAM_DESCRIPTION
+#' @return OUTPUT_DESCRIPTION
+#' @details DETAILS
+#' @examples
+#' \dontrun{
+#' if(interactive()){
+#' #EXAMPLE1
+#' }
+#' }
+#' @seealso
+#' \code{\link[tigris]{counties}}, \code{\link[tigris]{states}}
+#' \code{\link[dplyr]{select}}, \code{\link[dplyr]{mutate-joins}}, \code{\link[dplyr]{cross_join}}
+#' \code{\link[stats]{filter}}
+#' @rdname ojo_add_geometries
+#' @export
+#' @author Anthony Flores
+#' @importFrom tigris counties states
+#' @importFrom dplyr select left_join cross_join
+#' @importFrom stats filter
ojo_add_geometries <- function(data, geography = c("county", "state"), ...) {
geography <- geography[1]
if (geography == "county") {
- data <- counties("OK", progress_bar = FALSE, ...) |>
- select(GEOID) |>
- left_join(data)
+ data <- tigris::counties("OK", progress_bar = FALSE, ...) |>
+ dplyr::select(GEOID) |>
+ dplyr::left_join(data)
return(data)
}
if (geography == "state") {
- data <- states(progress_bar = FALSE, ...) |>
- filter(NAME == "Oklahoma") |>
- select(geometry) |>
- cross_join(data)
+ data <- tigris::states(progress_bar = FALSE, ...) |>
+ stats::filter(NAME == "Oklahoma") |>
+ dplyr::select(geometry) |>
+ dplyr::cross_join(data)
}
return(data)
diff --git a/R/ojo_add_month_and_year.R b/R/ojo_add_month_and_year.R
index f1dc7cc..cdb704a 100644
--- a/R/ojo_add_month_and_year.R
+++ b/R/ojo_add_month_and_year.R
@@ -1,6 +1,30 @@
library(dplyr)
library(lubridate)
library(purrr)
+#' @title FUNCTION_TITLE
+#' @description FUNCTION_DESCRIPTION
+#' @param data PARAM_DESCRIPTION
+#' @param ... PARAM_DESCRIPTION
+#' @return OUTPUT_DESCRIPTION
+#' @details DETAILS
+#' @examples
+#' \dontrun{
+#' if(interactive()){
+#' #EXAMPLE1
+#' }
+#' }
+#' @seealso
+#' \code{\link[rlang]{defusing-advanced}}, \code{\link[rlang]{quo_label}}, \code{\link[rlang]{sym}}
+#' \code{\link[purrr]{map}}
+#' \code{\link[dplyr]{mutate}}
+#' \code{\link[lubridate]{round_date}}
+#' @rdname ojo_add_month_and_year
+#' @export
+#' @author Anthony Flores
+#' @importFrom rlang quos quo_text sym
+#' @importFrom purrr map_chr
+#' @importFrom dplyr mutate
+#' @importFrom lubridate floor_date
ojo_add_month_and_year <- function(data, ...) {
"Add month and year columns. Uses columns with 'date' by default but
user can input the ones they want manually."
@@ -19,9 +43,9 @@ ojo_add_month_and_year <- function(data, ...) {
year_name <- if (colname == "date") "year" else paste0("year_", gsub("date_", "", colname))
data <- data %>%
- mutate(
- !!month_name := floor_date(!!sym(colname), "month"),
- !!year_name := floor_date(!!sym(colname), "year")
+ dplyr::mutate(
+ !!month_name := lubridate::floor_date(!!rlang::sym(colname), "month"),
+ !!year_name := lubridate::floor_date(!!rlang::sym(colname), "year")
)
}
diff --git a/R/ojo_add_population.R b/R/ojo_add_population.R
index 3553696..1a66bb5 100644
--- a/R/ojo_add_population.R
+++ b/R/ojo_add_population.R
@@ -1,129 +1,153 @@
-library(tidyr)
-library(stringr)
+#' @title FUNCTION_TITLE
+#' @description FUNCTION_DESCRIPTION
+#' @param data PARAM_DESCRIPTION
+#' @param geography PARAM_DESCRIPTION, Default: c("both", "county", "state")
+#' @param year_column PARAM_DESCRIPTION
+#' @param individual_year PARAM_DESCRIPTION, Default: NA
+#' @param ... PARAM_DESCRIPTION
+#' @return OUTPUT_DESCRIPTION
+#' @details DETAILS
+#' @examples
+#' \dontrun{
+#' if(interactive()){
+#' #EXAMPLE1
+#' }
+#' }
+#' @seealso
+#' \code{\link[dplyr]{select}}, \code{\link[dplyr]{reexports}}, \code{\link[dplyr]{nth}}, \code{\link[dplyr]{pull}}, \code{\link[dplyr]{mutate}}, \code{\link[dplyr]{bind_rows}}, \code{\link[dplyr]{mutate-joins}}, \code{\link[dplyr]{join_by}}
+#' \code{\link[lubridate]{year}}, \code{\link[lubridate]{ymd}}
+#' \code{\link[tidycensus]{get_estimates}}
+#' \code{\link[stats]{filter}}
+#' \code{\link[tidyr]{pivot_wider}}
+#' @rdname ojo_add_population
+#' @export
+#' @author Anthony Flores
+#' @importFrom dplyr select starts_with nth pull tibble mutate bind_rows left_join join_by
+#' @importFrom lubridate year ymd
+#' @importFrom tidycensus get_estimates
+#' @importFrom stats filter
+#' @importFrom tidyr pivot_wider
ojo_add_population <- function(data,
geography = c("both", "county", "state"),
year_column,
individual_year = NA,
- ...
- ) {
-
- "Adds population data from the Census Population Estimate Program."
-
- # TODO: Add option for population density
-
- ## Variable Handling
- # By default geography gets both the county and state
- .geography <- geography[1]
-
- # Add GEOIDs
- data <- data |>
- ojo_add_geoid(geography = "county", 2020)
-
- if (missing(year_column)) {
- # Find year columns in data, select first one in alphabetical order.
- year_column <- data |>
- select(starts_with("year")) |>
- names() |>
- sort() |>
- nth(1)
- }
-
- years <- data |>
- pull({{year_column}}) |>
- unique() |>
- year()
-
- get_population_data <- function(years, geography) {
-
- population_data <- tibble()
-
- #TODO: Need to use censusapi to get the 2000s and earlier PEP estimates.
- # if (any(years %in% 2000:2009)) {
- # population_2000s <- tidycensus::get_estimates(
- # product = "population",
- # geography = geography,
- # year = 2009,
- # time_series = TRUE,
- # state = "OK"
- # ) |>
- # filter(
- # variable == "POP",
- # !(DATE %in% c(1, 12)) # Excludes years 2010, and 2020 (https://www.census.gov/data/developers/data-sets/popest-popproj/popest/popest-vars/2019.html)
- # ) |>
- # mutate(
- # year = 2000 + (DATE - 2),
- # variable = "POPESTIMATE"
- # )
- #
- # population_data <- population_data |>
- # bind_rows(population_2000s)
- # }
-
- if (any(years %in% 2010:2019)) {
- population_2010s <- tidycensus::get_estimates(
- product = "population",
- geography = geography,
- year = 2019,
- time_series = TRUE,
- state = "OK"
- ) |>
- filter(
+ ...) {
+ "Adds population data from the Census Population Estimate Program."
+
+ # TODO: Add option for population density
+
+ ## Variable Handling
+ # By default geography gets both the county and state
+ .geography <- geography[1]
+
+ # Add GEOIDs
+ data <- data |>
+ ojo_add_geoid(geography = "county", 2020)
+
+ if (missing(year_column)) {
+ # Find year columns in data, select first one in alphabetical order.
+ year_column <- data |>
+ dplyr::select(dplyr::starts_with("year")) |>
+ names() |>
+ sort() |>
+ dplyr::nth(1)
+ }
+
+ years <- data |>
+ dplyr::pull({{ year_column }}) |>
+ unique() |>
+ lubridate::year()
+
+ get_population_data <- function(years, geography) {
+ population_data <- dplyr::tibble()
+
+ # TODO: Need to use censusapi to get the 2000s and earlier PEP estimates.
+ # if (any(years %in% 2000:2009)) {
+ # population_2000s <- tidycensus::get_estimates(
+ # product = "population",
+ # geography = geography,
+ # year = 2009,
+ # time_series = TRUE,
+ # state = "OK"
+ # ) |>
+ # filter(
+ # variable == "POP",
+ # !(DATE %in% c(1, 12)) # Excludes years 2010, and 2020 (https://www.census.gov/data/developers/data-sets/popest-popproj/popest/popest-vars/2019.html)
+ # ) |>
+ # mutate(
+ # year = 2000 + (DATE - 2),
+ # variable = "POPESTIMATE"
+ # )
+ #
+ # population_data <- population_data |>
+ # bind_rows(population_2000s)
+ # }
+
+ if (any(years %in% 2010:2019)) {
+ population_2010s <- tidycensus::get_estimates(
+ product = "population",
+ geography = geography,
+ year = 2019,
+ time_series = TRUE,
+ state = "OK"
+ ) |>
+ stats::filter(
variable == "POP",
!(DATE %in% c(1, 12))
) |>
- mutate(
+ dplyr::mutate(
year = 2010 + (DATE - 2),
variable = "POPESTIMATE"
)
- population_data <- population_data |>
- bind_rows(population_2010s)
- }
-
- if (any(years %in% 2020:2029)) {
- population_2020s <- tidycensus::get_estimates(
- product = "population",
- geography = geography,
- time_series = TRUE,
- state = "OK"
- ) |>
- filter(variable == "POPESTIMATE")
+ population_data <- population_data |>
+ dplyr::bind_rows(population_2010s)
+ }
- population_data <- population_data |>
- bind_rows(population_2020s)
- }
+ if (any(years %in% 2020:2029)) {
+ population_2020s <- tidycensus::get_estimates(
+ product = "population",
+ geography = geography,
+ time_series = TRUE,
+ state = "OK"
+ ) |>
+ stats::filter(variable == "POPESTIMATE")
population_data <- population_data |>
- pivot_wider(names_from = "variable", values_from = "value") |>
- mutate(year = paste0(year, "-01-01") |> ymd()) |>
- select(year, GEOID, population_county = POPESTIMATE)
+ dplyr::bind_rows(population_2020s)
+ }
- if (geography == "state") {
- population_data <- population_data |>
- select(year, population_state = population_county)
- }
+ population_data <- population_data |>
+ tidyr::pivot_wider(names_from = "variable", values_from = "value") |>
+ dplyr::mutate(year = paste0(year, "-01-01") |> lubridate::ymd()) |>
+ dplyr::select(year, GEOID, population_county = POPESTIMATE)
- return(population_data)
+ if (geography == "state") {
+ population_data <- population_data |>
+ dplyr::select(year, population_state = population_county)
}
- if (.geography %in% c("state", "both")) {
- population_state_data <- get_population_data(years, "state")
- data <- data |>
- left_join(population_state_data, by = join_by(!!year_column == year)) |>
- mutate(population_state = as.numeric(population_state)) # as.numeric() is necessary for this to work.
- }
- if (.geography %in% c("county", "both")) {
- population_county_data <- get_population_data(years, "county")
+ return(population_data)
+ }
- data <- data |>
- left_join(population_county_data, by = join_by(!!year_column == year, GEOID)) |>
- mutate(population_county = as.numeric(population_county))
- }
+ if (.geography %in% c("state", "both")) {
+ population_state_data <- get_population_data(years, "state")
+ data <- data |>
+ dplyr::left_join(population_state_data, by = dplyr::join_by(!!year_column == year)) |>
+ dplyr::mutate(population_state = as.numeric(population_state)) # as.numeric() is necessary for this to work.
+ }
+ if (.geography %in% c("county", "both")) {
+ population_county_data <- get_population_data(years, "county")
+
+ data <- data |>
+ dplyr::left_join(population_county_data, by = dplyr::join_by(!!year_column == year, GEOID)) |>
+ dplyr::mutate(population_county = as.numeric(population_county))
+ }
- cat(
- paste("Joined population on the", paste0("`", year_column, "`"), "column."),
- sep = "\n"
- )
+ cat(
+ paste("Joined population on the", paste0("`", year_column, "`"), "column."),
+ sep = "\n"
+ )
- return(data)
+ return(data)
}
diff --git a/R/ojo_aggregate.R b/R/ojo_aggregate.R
index dd60bce..de21b47 100644
--- a/R/ojo_aggregate.R
+++ b/R/ojo_aggregate.R
@@ -1,90 +1,107 @@
+#' @title FUNCTION_TITLE
+#' @description FUNCTION_DESCRIPTION
+#' @param data PARAM_DESCRIPTION
+#' @param ... PARAM_DESCRIPTION
+#' @param group_by PARAM_DESCRIPTION
+#' @param geography PARAM_DESCRIPTION, Default: c("county", "state")
+#' @param rate PARAM_DESCRIPTION, Default: 10^3
+#' @param rate_suffix PARAM_DESCRIPTION, Default: '1k'
+#' @return OUTPUT_DESCRIPTION
+#' @details DETAILS
+#' @examples
+#' \dontrun{
+#' if(interactive()){
+#' #EXAMPLE1
+#' }
+#' }
+#' @seealso
+#' \code{\link[rlang]{enquo}}, \code{\link[rlang]{quosure-tools}}, \code{\link[rlang]{as_label}}
+#' \code{\link[purrr]{map}}
+#' \code{\link[dplyr]{if_else}}, \code{\link[dplyr]{distinct}}, \code{\link[dplyr]{count}}, \code{\link[dplyr]{mutate}}, \code{\link[dplyr]{arrange}}
+#' @rdname ojo_aggregate
+#' @export
+#' @author Anthony Flores
+#' @importFrom rlang enquos quo_get_expr as_label
+#' @importFrom purrr map_chr
+#' @importFrom dplyr if_else distinct count mutate arrange
ojo_aggregate <- function(data,
...,
group_by,
geography = c("county", "state"),
rate = 10^3,
- rate_suffix = "1k"
- ) {
-
- # Variable Handling
- geography <- geography[1]
- variables <- enquos(...)
- if (!missing(group_by)) {
- group_by_text <- enquos(group_by) |> purrr::map_chr(~ rlang::quo_get_expr(.) |> rlang::as_label())
- }
-
- if (length(variables) == 0) {
- variable_name <- NA
- } else {
- variable_name <- purrr::map_chr(variables, ~ rlang::as_label(.))
+ rate_suffix = "1k") {
+ # Variable Handling
+ geography <- geography[1]
+ variables <- rlang::enquos(...)
+ if (!missing(group_by)) {
+ group_by_text <- rlang::enquos(group_by) |> purrr::map_chr(~ rlang::quo_get_expr(.) |> rlang::as_label())
+ }
+
+ if (length(variables) == 0) {
+ variable_name <- NA
+ } else {
+ variable_name <- purrr::map_chr(variables, ~ rlang::as_label(.))
+ }
+
+ n_variable_name <- dplyr::if_else(
+ is.na(variable_name),
+ "n",
+ paste0("n_", variable_name) # E.g., n_eviction_filings
+ )
+ rate_variable_name <- dplyr::if_else(
+ is.na(variable_name),
+ paste0("n_", "per_", rate_suffix),
+ paste0("n_", variable_name, "_per_", rate_suffix) # E.g., n_eviction_filings_per1k
+ )
+
+ data <- data |>
+ dplyr::distinct(id, .keep_all = TRUE)
+
+ if (any(is.na(variable_name))) {
+ variable_name <- ""
+
+ if (geography == "county") {
+ data <- data |>
+ dplyr::count({{ group_by }}, district, population_county, name = n_variable_name)
+ } else if (geography == "state") {
+ data <- data |>
+ dplyr::count({{ group_by }}, population_state, name = n_variable_name)
+
+ data <- data |>
+ dplyr::mutate(
+ !!rate_variable_name := .data[[n_variable_name]] / population_state * rate
+ ) |>
+ dplyr::arrange({{ group_by }}, !!variable_name)
+
+ return(data)
}
-
- n_variable_name <- if_else(
- is.na(variable_name),
- "n",
- paste0("n_", variable_name) # E.g., n_eviction_filings
- )
- rate_variable_name <- if_else(
- is.na(variable_name),
- paste0("n_", "per_", rate_suffix),
- paste0("n_", variable_name, "_per_", rate_suffix) # E.g., n_eviction_filings_per1k
- )
-
- data <- data |>
- distinct(id, .keep_all = TRUE)
-
- if (any(is.na(variable_name))) {
- variable_name <- ""
-
- if (geography == "county") {
-
- data <- data |>
- count({{group_by}}, district, population_county, name = n_variable_name)
-
- } else if (geography == "state") {
-
- data <- data |>
- count({{group_by}}, population_state, name = n_variable_name)
-
- data <- data |>
- mutate(
- !!rate_variable_name := .data[[n_variable_name]] / population_state * rate
- ) |>
- arrange({{group_by}}, !!variable_name)
-
- return(data)
-
- }
- } else {
- if (geography == "county") {
-
- data <- data |>
- count(
- {{group_by}}, district, population_county, .data[[variable_name]],
- name = n_variable_name
- )
-
- } else if (geography == "state") {
-
- data <- data |>
- count(
- {{group_by}}, district, population_county, .data[[variable_name]],
- name = n_variable_name
- )
-
- data <- data |>
- mutate(
- !!rate_variable_name := .data[[n_variable_name]] / population_state * rate
- ) |>
- arrange({{group_by}}, !!variable_name)
-
- return(data)
- }
+ } else {
+ if (geography == "county") {
+ data <- data |>
+ dplyr::count(
+ {{ group_by }}, district, population_county, .data[[variable_name]],
+ name = n_variable_name
+ )
+ } else if (geography == "state") {
+ data <- data |>
+ dplyr::count(
+ {{ group_by }}, district, population_county, .data[[variable_name]],
+ name = n_variable_name
+ )
+
+ data <- data |>
+ dplyr::mutate(
+ !!rate_variable_name := .data[[n_variable_name]] / population_state * rate
+ ) |>
+ dplyr::arrange({{ group_by }}, !!variable_name)
+
+ return(data)
}
+ }
- data <- data |>
- mutate(!!rate_variable_name := .data[[n_variable_name]] / population_county * rate) |>
- arrange({{group_by}}, district, !!variable_name)
+ data <- data |>
+ dplyr::mutate(!!rate_variable_name := .data[[n_variable_name]] / population_county * rate) |>
+ dplyr::arrange({{ group_by }}, district, !!variable_name)
- return(data)
+ return(data)
}
diff --git a/R/ojo_district_and_date_filters.R b/R/ojo_district_and_date_filters.R
index 119f6a9..ddb3063 100644
--- a/R/ojo_district_and_date_filters.R
+++ b/R/ojo_district_and_date_filters.R
@@ -1,25 +1,45 @@
+#' @title FUNCTION_TITLE
+#' @description FUNCTION_DESCRIPTION
+#' @param data PARAM_DESCRIPTION
+#' @param districts PARAM_DESCRIPTION, Default: 'ALL'
+#' @param date_start PARAM_DESCRIPTION, Default: NA
+#' @param date_end PARAM_DESCRIPTION, Default: NA
+#' @param district_variable PARAM_DESCRIPTION, Default: 'district'
+#' @param date_variable PARAM_DESCRIPTION, Default: 'date_filed'
+#' @return OUTPUT_DESCRIPTION
+#' @details DETAILS
+#' @examples
+#' \dontrun{
+#' if(interactive()){
+#' #EXAMPLE1
+#' }
+#' }
+#' @seealso
+#' \code{\link[dplyr]{filter}}
+#' @rdname ojo_district_and_date_filters
+#' @export
+#' @author Anthony Flores
+#' @importFrom dplyr filter
ojo_district_and_date_filters <- function(data,
districts = "ALL",
date_start = NA,
date_end = NA,
district_variable = "district",
- date_variable = "date_filed"
- ) {
+ date_variable = "date_filed") {
+ "Helper function for commonly used case filters."
- "Helper function for commonly used case filters."
+ # Variable Handling
+ .districts <- toupper(districts)
- # Variable Handling
- .districts <- toupper(districts)
+ if (any(districts != "ALL")) {
+ data <- data |> dplyr::filter(.data[[district_variable]] %in% .districts)
+ }
+ if (!is.na(date_end)) {
+ data <- data |> dplyr::filter(.data[[date_variable]] <= date_end)
+ }
+ if (!is.na(date_start)) {
+ data <- data |> dplyr::filter(.data[[date_variable]] >= date_start)
+ }
- if (any(districts != "ALL")) {
- data <- data |> filter(.data[[district_variable]] %in% .districts)
- }
- if (!is.na(date_end)) {
- data <- data |> filter(.data[[date_variable]] <= date_end)
- }
- if (!is.na(date_start)) {
- data <- data |> filter(.data[[date_variable]] >= date_start)
- }
-
- return(data)
+ return(data)
}
diff --git a/R/ojo_highchart_map.R b/R/ojo_highchart_map.R
index 4acbd58..c35e672 100644
--- a/R/ojo_highchart_map.R
+++ b/R/ojo_highchart_map.R
@@ -1,20 +1,52 @@
-library(ggthemes)
-library(jsonlite)
-library(geojsonsf)
-library(highcharter)
+#' @title FUNCTION_TITLE
+#' @description FUNCTION_DESCRIPTION
+#' @param data PARAM_DESCRIPTION
+#' @param variable PARAM_DESCRIPTION
+#' @param ... PARAM_DESCRIPTION
+#' @param caption PARAM_DESCRIPTION, Default: NULL
+#' @param nbins PARAM_DESCRIPTION
+#' @param map_color_stops PARAM_DESCRIPTION, Default: rev(viridis::magma(n = 3))
+#' @return OUTPUT_DESCRIPTION
+#' @details DETAILS
+#' @examples
+#' \dontrun{
+#' if(interactive()){
+#' #EXAMPLE1
+#' }
+#' }
+#' @seealso
+#' \code{\link[viridis]{reexports}}
+#' \code{\link[rlang]{enquo}}, \code{\link[rlang]{as_label}}
+#' \code{\link[dplyr]{select}}, \code{\link[dplyr]{pull}}, \code{\link[dplyr]{reexports}}
+#' \code{\link[geojsonsf]{sf_geojson}}
+#' \code{\link[jsonlite]{toJSON, fromJSON}}
+#' \code{\link[stats]{na.fail}}
+#' \code{\link[grDevices]{nclass}}
+#' \code{\link[graphics]{hist}}
+#' \code{\link[highcharter]{color_classes}}, \code{\link[highcharter]{color_stops}}, \code{\link[highcharter]{highchart}}, \code{\link[highcharter]{hc_add_series_map}}, \code{\link[highcharter]{hc_caption}}, \code{\link[highcharter]{hc_colorAxis}}, \code{\link[highcharter]{hc_legend}}, \code{\link[highcharter]{hc_mapNavigation}}, \code{\link[highcharter]{hc_add_theme}}
+#' @rdname ojo_highchart_map
+#' @export
+#' @author Anthony Flores
+#' @importFrom viridis magma
+#' @importFrom rlang enquo as_label
+#' @importFrom dplyr select pull tibble
+#' @importFrom geojsonsf sf_geojson
+#' @importFrom jsonlite fromJSON
+#' @importFrom stats na.omit
+#' @importFrom grDevices nclass.FD
+#' @importFrom graphics hist
+#' @importFrom highcharter color_classes color_stops highchart hc_add_series_map hc_caption hc_colorAxis hc_legend hc_mapNavigation hc_add_theme
ojo_highchart_map <- function(data,
variable,
...,
caption = NULL,
nbins,
- map_color_stops = rev(viridis::magma(n = 3))
- ) {
-
- variable <- enquo(variable) |> rlang::as_label()
+ map_color_stops = rev(viridis::magma(n = 3))) {
+ variable <- rlang::enquo(variable) |> rlang::as_label()
data_json <- data |>
- select(district) |>
+ dplyr::select(district) |>
geojsonsf::sf_geojson() |>
jsonlite::fromJSON(simplifyVector = FALSE)
@@ -34,10 +66,10 @@ ojo_highchart_map <- function(data,
# variable_data <- data_hc |>
variable_data <- data |>
- pull({{variable}}) |>
- na.omit()
+ dplyr::pull({{ variable }}) |>
+ stats::na.omit()
- n_bins <- nclass.FD(variable_data)
+ n_bins <- grDevices::nclass.FD(variable_data)
if (!missing(nbins)) {
n_bins <- nbins
@@ -47,28 +79,28 @@ ojo_highchart_map <- function(data,
}
}
- h <- hist(variable_data, plot = FALSE, breaks = n_bins)
+ h <- graphics::hist(variable_data, plot = FALSE, breaks = n_bins)
d <- diff(h$breaks)[1]
- df <- tibble(
- x = h$mids,
- y = h$counts,
- name = sprintf("(%s, %s]", h$mids - d / 2, h$mids + d / 2)
- )
+ df <- dplyr::tibble(
+ x = h$mids,
+ y = h$counts,
+ name = sprintf("(%s, %s]", h$mids - d / 2, h$mids + d / 2)
+ )
- legend_colors <- color_classes(
- breaks = h$breaks,
- colors =
- color_stops(
- n = n_bins,
- colors = map_color_stops
- ) |>
- sapply(function(x) x[[2]])
+ legend_colors <- highcharter::color_classes(
+ breaks = h$breaks,
+ colors =
+ highcharter::color_stops(
+ n = n_bins,
+ colors = map_color_stops
+ ) |>
+ sapply(function(x) x[[2]])
)
- hc <- highchart() |>
- hc_add_series_map(
+ hc <- highcharter::highchart() |>
+ highcharter::hc_add_series_map(
map = data_json,
df = data,
joinBy = "district",
@@ -76,50 +108,50 @@ ojo_highchart_map <- function(data,
name = pretty_variable_names(variable),
value = variable,
tooltip = list(
- headerFormat = "{point.name}
",
- pointFormatter = highchart_label_formatter(
- variable,
- prefix = "'' + this.district + '
' + this.series.name + ': ' + ",
- suffix = " + '
'",
- # "+ 'Margin of Error:,
- # paste0("this.moe_", variable),
- # "±'",
- digits = 1
- )
+ headerFormat = "{point.name}
",
+ pointFormatter = highchart_label_formatter(
+ variable,
+ prefix = "'' + this.district + '
' + this.series.name + ': ' + ",
+ suffix = " + '
'",
+ # "+ 'Margin of Error:,
+ # paste0("this.moe_", variable),
+ # "±'",
+ digits = 1
+ )
),
dataLabels = list(
enabled = TRUE,
format = "{point.district}"
)
) |>
- hc_caption(text = caption) |>
- hc_colorAxis(
- labels = list(
- format = "{value}",
- formatter = highchart_label_formatter(variable)
- ),
- dataClasses = legend_colors
+ highcharter::hc_caption(text = caption) |>
+ highcharter::hc_colorAxis(
+ labels = list(
+ format = "{value}",
+ formatter = highchart_label_formatter(variable)
+ ),
+ dataClasses = legend_colors
) |>
- hc_legend(
- layout = "vertical",
- align = "left",
- verticalAlign = "top",
- floating = TRUE,
- backgroundColor = 'rgba(255,255,255,0.9)',
- valueDecimals = 2,
- labelFormatter = highchart_label_formatter(variable, dataClass = TRUE),
- symbolRadius = 0,
- itemMarginBottom = 4,
- itemMarginTop = 4,
- shadow = TRUE
+ highcharter::hc_legend(
+ layout = "vertical",
+ align = "left",
+ verticalAlign = "top",
+ floating = TRUE,
+ backgroundColor = "rgba(255,255,255,0.9)",
+ valueDecimals = 2,
+ labelFormatter = highchart_label_formatter(variable, dataClass = TRUE),
+ symbolRadius = 0,
+ itemMarginBottom = 4,
+ itemMarginTop = 4,
+ shadow = TRUE
) |>
- hc_mapNavigation(
- enabled = TRUE,
- buttonOptions = list(
- align = "right"
- )
+ highcharter::hc_mapNavigation(
+ enabled = TRUE,
+ buttonOptions = list(
+ align = "right"
+ )
) |>
- hc_add_theme(hc_theme_ojo)
+ highcharter::hc_add_theme(hc_theme_ojo)
return(hc)
}
diff --git a/R/ojo_optional_filter.R b/R/ojo_optional_filter.R
index cc6a0f7..8ab5e96 100644
--- a/R/ojo_optional_filter.R
+++ b/R/ojo_optional_filter.R
@@ -1,9 +1,28 @@
+#' @title FUNCTION_TITLE
+#' @description FUNCTION_DESCRIPTION
+#' @param data PARAM_DESCRIPTION
+#' @param variable PARAM_DESCRIPTION
+#' @param variable_values PARAM_DESCRIPTION, Default: NA
+#' @return OUTPUT_DESCRIPTION
+#' @details DETAILS
+#' @examples
+#' \dontrun{
+#' if(interactive()){
+#' #EXAMPLE1
+#' }
+#' }
+#' @seealso
+#' \code{\link[dplyr]{filter}}
+#' @rdname ojo_optional_filter
+#' @export
+#' @author Anthony Flores
+#' @importFrom dplyr filter
ojo_optional_filter <- function(data, variable, variable_values = NA) {
- "Helper for optional filtering of variable if not NA."
+ "Helper for optional filtering of variable if not NA."
- if (any(!is.na(variable_values))) {
- data <- data |> filter({{variable}} %in% variable_values)
- }
+ if (any(!is.na(variable_values))) {
+ data <- data |> dplyr::filter({{ variable }} %in% variable_values)
+ }
- return(data)
+ return(data)
}
diff --git a/R/ojo_plot_lines.R b/R/ojo_plot_lines.R
index 3e6c835..63342cb 100644
--- a/R/ojo_plot_lines.R
+++ b/R/ojo_plot_lines.R
@@ -1,32 +1,64 @@
-library(ojodb)
-library(ggplot2)
-
+#' @title FUNCTION_TITLE
+#' @description FUNCTION_DESCRIPTION
+#' @param data PARAM_DESCRIPTION
+#' @param x PARAM_DESCRIPTION
+#' @param y PARAM_DESCRIPTION
+#' @param ... PARAM_DESCRIPTION
+#' @param color_variable PARAM_DESCRIPTION, Default: variable
+#' @param facet_variable PARAM_DESCRIPTION, Default: NA
+#' @param legend_labels PARAM_DESCRIPTION, Default: NA
+#' @param facet_labels PARAM_DESCRIPTION, Default: NA
+#' @param custom_color_palette PARAM_DESCRIPTION, Default: NA
+#' @param number_of_columns PARAM_DESCRIPTION, Default: 1
+#' @param data_to_highlight PARAM_DESCRIPTION, Default: NA
+#' @param highlight_color PARAM_DESCRIPTION, Default: 'red'
+#' @param theme PARAM_DESCRIPTION, Default: custom_ojo_theme()
+#' @param add_covid_labels PARAM_DESCRIPTION, Default: FALSE
+#' @return OUTPUT_DESCRIPTION
+#' @details DETAILS
+#' @examples
+#' \dontrun{
+#' if(interactive()){
+#' #EXAMPLE1
+#' }
+#' }
+#' @seealso
+#' \code{\link[stringr]{str_flatten}}
+#' \code{\link[dplyr]{if_else}}, \code{\link[dplyr]{select}}, \code{\link[dplyr]{reexports}}, \code{\link[dplyr]{distinct}}, \code{\link[dplyr]{pull}}, \code{\link[dplyr]{summarise}}
+#' \code{\link[tidyr]{pivot_longer}}
+#' \code{\link[ggplot2]{ggplot}}, \code{\link[ggplot2]{aes}}, \code{\link[ggplot2]{geom_path}}, \code{\link[ggplot2]{geom_point}}, \code{\link[ggplot2]{facet_wrap}}, \code{\link[ggplot2]{vars}}, \code{\link[ggplot2]{as_labeller}}, \code{\link[ggplot2]{theme}}, \code{\link[ggplot2]{margin}}, \code{\link[ggplot2]{scale_continuous}}, \code{\link[ggplot2]{scale_manual}}, \code{\link[ggplot2]{c("guide_bins", "guide_colourbar", "guide_coloursteps", "guide_legend", "guides", "guides")}}, \code{\link[ggplot2]{guide_legend}}
+#' \code{\link[scales]{label_number}}
+#' @rdname ojo_plot_lines
+#' @export
+#' @author Anthony Flores
+#' @importFrom stringr str_flatten
+#' @importFrom dplyr if_else select matches distinct pull any_of summarise
+#' @importFrom tidyr pivot_longer
+#' @importFrom ggplot2 ggplot aes geom_line geom_point facet_wrap vars as_labeller theme element_blank scale_y_continuous scale_color_manual guides guide_legend
+#' @importFrom scales label_comma
ojo_plot_lines <- function(data,
- x,
- y,
- ...,
- color_variable = variable,
- facet_variable = NA,
- # legend_labels = "default",
- # facet_labels = "default",
- legend_labels = NA,
- facet_labels = NA,
- custom_color_palette = NA,
- number_of_columns = 1,
- data_to_highlight = NA,
- highlight_color = "red",
- theme = custom_ojo_theme(),
- add_covid_labels = FALSE
-) {
-
-
+ x,
+ y,
+ ...,
+ color_variable = variable,
+ facet_variable = NA,
+ # legend_labels = "default",
+ # facet_labels = "default",
+ legend_labels = NA,
+ facet_labels = NA,
+ custom_color_palette = NA,
+ number_of_columns = 1,
+ data_to_highlight = NA,
+ highlight_color = "red",
+ theme = custom_ojo_theme(),
+ add_covid_labels = FALSE) {
# Create strings from inputs
x_string <- deparse(substitute(x))
if (is.symbol(substitute(y)) | is.language(substitute(y))) {
y_string <- deparse(substitute(y))
} else if (is.language(substitute(y))) {
y_string <- sapply(substitute(y)[-1], function(x) deparse(x))
- y_string <- str_flatten(y_string)
+ y_string <- stringr::str_flatten(y_string)
} else {
y_string <- y
}
@@ -37,10 +69,10 @@ ojo_plot_lines <- function(data,
}
# Regex selection of the x, y, and color_variable columns.
- regex_columns <-paste0(
+ regex_columns <- paste0(
x_string,
"|",
- if_else(
+ dplyr::if_else(
color_variable_string == "",
"",
paste0(color_variable_string, "|")
@@ -50,45 +82,47 @@ ojo_plot_lines <- function(data,
plotData <-
data |>
- select(matches(regex_columns))
+ dplyr::select(dplyr::matches(regex_columns))
# Construct wide data to input to ggplot based on the color_variable input
if (color_variable_string == "") {
plotData <-
plotData |>
- pivot_longer(!{{x}}, names_to = "variable", values_to = "value")
+ tidyr::pivot_longer(!{{ x }}, names_to = "variable", values_to = "value")
p <-
plotData |>
- ggplot(aes(x = {{x}}, y = value, color = variable))
+ ggplot2::ggplot(ggplot2::aes(x = {{ x }}, y = value, color = variable))
number_of_variables <-
plotData |>
- distinct(variable) |>
- pull() |>
+ dplyr::distinct(variable) |>
+ dplyr::pull() |>
length()
} else {
plotData <-
plotData |>
- pivot_longer(
- !any_of(c(x_string, color_variable_string)),
+ tidyr::pivot_longer(
+ !dplyr::any_of(c(x_string, color_variable_string)),
names_to = "variable", values_to = "value"
)
p <-
plotData |>
- ggplot(aes(x = {{x}}, y = value, color = {{color_variable}}))
+ ggplot2::ggplot(ggplot2::aes(x = {{ x }}, y = value, color = {{ color_variable }}))
number_of_variables <-
plotData |>
- distinct({{color_variable}}) |>
- pull() |>
+ dplyr::distinct({{ color_variable }}) |>
+ dplyr::pull() |>
length()
}
# Format labels for use in ggplot
if (any(!is.na(legend_labels))) {
- legend_variables <- plotData |> distinct(variable) |> pull()
+ legend_variables <- plotData |>
+ dplyr::distinct(variable) |>
+ dplyr::pull()
names(legend_labels) <- legend_variables
}
# if (any(!is.na(facet_labels))) {
@@ -100,37 +134,38 @@ ojo_plot_lines <- function(data,
if (add_covid_labels == TRUE) {
labelData <-
plotData |>
- summarise(maxValue = max(value), .by = variable)
+ dplyr::summarise(maxValue = max(value), .by = variable)
p <- p +
covid_eviction_labels(label_data = labelData)
}
p <- p +
- geom_line(linewidth = 1.5) +
- geom_point(shape = 19, size = 2)
+ ggplot2::geom_line(linewidth = 1.5) +
+ ggplot2::geom_point(shape = 19, size = 2)
# Add optional highlighting of certain data points.
if (is.object(data_to_highlight)) {
data_to_highlight <-
data_to_highlight |>
- select(matches(regex_columns)) |>
- pivot_longer(
- !any_of(c(x_string, color_variable_string)),
+ dplyr::select(dplyr::matches(regex_columns)) |>
+ tidyr::pivot_longer(
+ !dplyr::any_of(c(x_string, color_variable_string)),
names_to = "variable", values_to = "value"
)
p <- p +
- geom_point(data = data_to_highlight, shape = 19, size = 2, color = highlight_color)
+ ggplot2::geom_point(data = data_to_highlight, shape = 19, size = 2, color = highlight_color)
}
p <- p +
- geom_point(shape = 21, size = 2, stroke = 1, color = "black")
+ ggplot2::geom_point(shape = 21, size = 2, stroke = 1, color = "black")
if (facet_variable_string != "NA") {
p <- p +
- facet_wrap(
- vars({{facet_variable}}), ncol = number_of_columns, scales = "free",
- labeller = as_labeller(facet_labels)
+ ggplot2::facet_wrap(
+ ggplot2::vars({{ facet_variable }}),
+ ncol = number_of_columns, scales = "free",
+ labeller = ggplot2::as_labeller(facet_labels)
)
}
@@ -140,34 +175,39 @@ ojo_plot_lines <- function(data,
}
p <- p +
- theme(
- axis.title = element_blank()
+ ggplot2::theme(
+ axis.title = ggplot2::element_blank()
)
- if (any(is.na(facet_labels)))
+ if (any(is.na(facet_labels))) {
p <- p +
- theme(
- strip.text = element_blank()
- )
+ ggplot2::theme(
+ strip.text = ggplot2::element_blank()
+ )
+ }
p <- p +
- scale_y_continuous(labels = scales::label_comma()) +
- scale_color_manual(values = ojo_pal[1:number_of_variables]) +
- guides(color = guide_legend(override.aes = list(
- shape = rep(19, number_of_variables), linetype = 0, size = 3, fill = NA
+ ggplot2::scale_y_continuous(labels = scales::label_comma()) +
+ ggplot2::scale_color_manual(values = ojo_pal[1:number_of_variables]) +
+ ggplot2::guides(color = ggplot2::guide_legend(
+ override.aes = list(
+ shape = rep(19, number_of_variables),
+ linetype = 0,
+ size = 3,
+ fill = NA
+ )
))
- )
# Customize color pallette
if (any(!is.na(custom_color_palette))) {
p <- p +
- scale_color_manual(values = custom_color_palette[1:number_of_variables])
+ ggplot2::scale_color_manual(values = custom_color_palette[1:number_of_variables])
}
# Add custom labels for legend
if (any(!is.na(legend_labels))) {
p <- p +
- scale_color_manual(
+ ggplot2::scale_color_manual(
values = ojo_pal[1:number_of_variables],
labels = legend_labels
)
diff --git a/R/pretty_variable_names.R b/R/pretty_variable_names.R
index 423fbdf..faa0fd8 100644
--- a/R/pretty_variable_names.R
+++ b/R/pretty_variable_names.R
@@ -1,15 +1,33 @@
+#' @title FUNCTION_TITLE
+#' @description FUNCTION_DESCRIPTION
+#' @param variable_names PARAM_DESCRIPTION
+#' @return OUTPUT_DESCRIPTION
+#' @details DETAILS
+#' @examples
+#' \dontrun{
+#' if(interactive()){
+#' #EXAMPLE1
+#' }
+#' }
+#' @seealso
+#' \code{\link[snakecase]{caseconverter}}
+#' \code{\link[stringr]{str_replace}}
+#' @rdname pretty_variable_names
+#' @export
+#' @author Anthony Flores
+#' @importFrom snakecase to_title_case
+#' @importFrom stringr str_replace_all
pretty_variable_names <- function(variable_names) {
+ pretty_names <- variable_names |>
+ snakecase::to_title_case() |>
+ stringr::str_replace_all(
+ pattern = "Percent Population",
+ replacement = "% of Population,"
+ ) |>
+ stringr::str_replace_all("Nhpi", "NHPI") |>
+ stringr::str_replace_all("Non Hispanic", "Non-Hispanic") |>
+ stringr::str_replace_all("^N\\s", "Number of ") |>
+ stringr::str_replace_all("\\sN\\s", "Number of ")
- pretty_names <- variable_names |>
- snakecase::to_title_case() |>
- str_replace_all(
- pattern = "Percent Population",
- replacement = "% of Population,"
- ) |>
- str_replace_all("Nhpi", "NHPI") |>
- str_replace_all("Non Hispanic", "Non-Hispanic") |>
- str_replace_all("^N\\s", "Number of ") |>
- str_replace_all("\\sN\\s", "Number of ")
-
- return(pretty_names)
+ return(pretty_names)
}
diff --git a/R/tably.R b/R/tably.R
index dfc6e32..02767db 100644
--- a/R/tably.R
+++ b/R/tably.R
@@ -1,41 +1,66 @@
-tably <- function (data, ..., print_n = NA, top_n = NA, sort = TRUE) {
+#' @title FUNCTION_TITLE
+#' @description FUNCTION_DESCRIPTION
+#' @param data PARAM_DESCRIPTION
+#' @param ... PARAM_DESCRIPTION
+#' @param print_n PARAM_DESCRIPTION, Default: NA
+#' @param top_n PARAM_DESCRIPTION, Default: NA
+#' @param sort PARAM_DESCRIPTION, Default: TRUE
+#' @return OUTPUT_DESCRIPTION
+#' @details DETAILS
+#' @examples
+#' \dontrun{
+#' if(interactive()){
+#' #EXAMPLE1
+#' }
+#' }
+#' @seealso
+#' \code{\link[rlang]{enquo}}, \code{\link[rlang]{sym}}
+#' \code{\link[dplyr]{count}}, \code{\link[dplyr]{mutate}}, \code{\link[dplyr]{slice}}, \code{\link[dplyr]{summarise}}
+#' @rdname tably
+#' @export
+#' @author Anthony Flores
+#' @importFrom rlang enquos sym
+#' @importFrom dplyr count mutate slice summarise
+tably <- function(data, ..., print_n = NA, top_n = NA, sort = TRUE) {
# TODO: add check for x is missing.
# TODO: add check for using print_n & top_n at the same time.
# Format arguments
.sort <- sort
- dots <- enquos(...)
+ dots <- rlang::enquos(...)
df <-
data |>
- count(!!!dots, sort = .sort) |>
- mutate(percent = n / sum(n) * 100,
- total_n = sum(n)
- )
+ dplyr::count(!!!dots, sort = .sort) |>
+ dplyr::mutate(
+ percent = n / sum(n) * 100,
+ total_n = sum(n)
+ )
# if you want to the output to print more than 10.
if (!is.na(print_n)) {
return(
df |>
- print(n = print_n)
+ print(n = print_n)
)
}
# Returns the frequency and percent frequency of the top n observations
# and of the observations not in the top n.
if (!is.na(top_n)) {
- df <-
- df |>
- slice(1:top_n) |>
- summarise(!!paste0("top", top_n, "_n") := sum(n),
- !!paste0("top", top_n, "_percent") := sum(percent),
- .by = total_n
- ) |>
- mutate(!!paste0("non_top", top_n, "_n") :=
- total_n - !!sym(paste0("top", top_n, "_n")),
- !!paste0("non_top", top_n, "_percent") :=
- 100 - !!sym(paste0("top", top_n, "_percent"))
- )
+ df <-
+ df |>
+ dplyr::slice(1:top_n) |>
+ dplyr::summarise(!!paste0("top", top_n, "_n") := sum(n),
+ !!paste0("top", top_n, "_percent") := sum(percent),
+ .by = total_n
+ ) |>
+ dplyr::mutate(
+ !!paste0("non_top", top_n, "_n") :=
+ total_n - !!rlang::sym(paste0("top", top_n, "_n")),
+ !!paste0("non_top", top_n, "_percent") :=
+ 100 - !!rlang::sym(paste0("top", top_n, "_percent"))
+ )
}
return(df)
diff --git a/_sinewconfig.yml b/_sinewconfig.yml
new file mode 100644
index 0000000..22920cd
--- /dev/null
+++ b/_sinewconfig.yml
@@ -0,0 +1,2 @@
+add_fields: ["author"]
+author: 'Anthony Flores'
diff --git a/man/covid_eviction_labels.Rd b/man/covid_eviction_labels.Rd
new file mode 100644
index 0000000..3a6a6e8
--- /dev/null
+++ b/man/covid_eviction_labels.Rd
@@ -0,0 +1,38 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/covid_eviction_labels.R
+\name{covid_eviction_labels}
+\alias{covid_eviction_labels}
+\title{FUNCTION_TITLE}
+\usage{
+covid_eviction_labels(label_data, ..., .labels = FALSE)
+}
+\arguments{
+\item{label_data}{PARAM_DESCRIPTION}
+
+\item{...}{PARAM_DESCRIPTION}
+
+\item{.labels}{PARAM_DESCRIPTION, Default: FALSE}
+}
+\value{
+OUTPUT_DESCRIPTION
+}
+\description{
+FUNCTION_DESCRIPTION
+}
+\details{
+DETAILS
+}
+\examples{
+\dontrun{
+if(interactive()){
+ #EXAMPLE1
+ }
+}
+}
+\seealso{
+\code{\link[ggplot2]{geom_label}}, \code{\link[ggplot2]{aes}}, \code{\link[ggplot2]{annotate}}, \code{\link[ggplot2]{geom_raster}}, \code{\link[ggplot2]{scale_manual}}, \code{\link[ggplot2]{guide_legend}}, \code{\link[ggplot2]{geom_abline}}
+\code{\link[lubridate]{ymd}}
+}
+\author{
+Anthony Flores
+}
diff --git a/man/custom_ojo_theme.Rd b/man/custom_ojo_theme.Rd
new file mode 100644
index 0000000..c283cb2
--- /dev/null
+++ b/man/custom_ojo_theme.Rd
@@ -0,0 +1,30 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/custom_ojo_theme.R
+\name{custom_ojo_theme}
+\alias{custom_ojo_theme}
+\title{FUNCTION_TITLE}
+\usage{
+custom_ojo_theme()
+}
+\value{
+OUTPUT_DESCRIPTION
+}
+\description{
+FUNCTION_DESCRIPTION
+}
+\details{
+DETAILS
+}
+\examples{
+\dontrun{
+if(interactive()){
+ #EXAMPLE1
+ }
+}
+}
+\seealso{
+\code{\link[ggplot2]{ggtheme}}, \code{\link[ggplot2]{theme}}, \code{\link[ggplot2]{margin}}
+}
+\author{
+Anthony Flores
+}
diff --git a/man/hc_theme_ojo.Rd b/man/hc_theme_ojo.Rd
new file mode 100644
index 0000000..9149b7f
--- /dev/null
+++ b/man/hc_theme_ojo.Rd
@@ -0,0 +1,31 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/hc_theme_ojo.R
+\name{hc_theme_ojo}
+\alias{hc_theme_ojo}
+\title{FUNCTION_TITLE}
+\usage{
+hc_theme_ojo()
+}
+\value{
+OUTPUT_DESCRIPTION
+}
+\description{
+FUNCTION_DESCRIPTION
+}
+\details{
+DETAILS
+}
+\examples{
+\dontrun{
+if(interactive()){
+ #EXAMPLE1
+ }
+}
+}
+\seealso{
+\code{\link[highcharter]{hc_theme_merge}}, \code{\link[highcharter]{hc_theme_smpl}}, \code{\link[highcharter]{hc_theme}}
+\code{\link[ojodb]{ojo_pal}}
+}
+\author{
+Anthony Flores
+}
diff --git a/man/hello.Rd b/man/hello.Rd
deleted file mode 100644
index e7eb880..0000000
--- a/man/hello.Rd
+++ /dev/null
@@ -1,20 +0,0 @@
-% Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/hello.R
-\name{hello}
-\alias{hello}
-\title{Personal greeting}
-\usage{
-hello(name = "your name")
-}
-\arguments{
-\item{name}{Your name (character string; e.g. "john doe").}
-}
-\value{
-A character string, capitalized to title case.
-}
-\description{
-Greet a person and appropriately capitalize their name.
-}
-\examples{
-hello("james bond")
-}
diff --git a/man/highchart_label_formatter.Rd b/man/highchart_label_formatter.Rd
new file mode 100644
index 0000000..2387b14
--- /dev/null
+++ b/man/highchart_label_formatter.Rd
@@ -0,0 +1,51 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/highchart_label_formatter.R
+\name{highchart_label_formatter}
+\alias{highchart_label_formatter}
+\title{FUNCTION_TITLE}
+\usage{
+highchart_label_formatter(
+ variable_name,
+ prefix = "",
+ suffix = "",
+ value_identifier = "this.value",
+ digits = 0,
+ dataClass = FALSE
+)
+}
+\arguments{
+\item{variable_name}{PARAM_DESCRIPTION}
+
+\item{prefix}{PARAM_DESCRIPTION, Default: ''}
+
+\item{suffix}{PARAM_DESCRIPTION, Default: ''}
+
+\item{value_identifier}{PARAM_DESCRIPTION, Default: 'this.value'}
+
+\item{digits}{PARAM_DESCRIPTION, Default: 0}
+
+\item{dataClass}{PARAM_DESCRIPTION, Default: FALSE}
+}
+\value{
+OUTPUT_DESCRIPTION
+}
+\description{
+FUNCTION_DESCRIPTION
+}
+\details{
+DETAILS
+}
+\examples{
+\dontrun{
+if(interactive()){
+ #EXAMPLE1
+ }
+}
+}
+\seealso{
+\code{\link[stringr]{str_detect}}, \code{\link[stringr]{str_replace}}
+\code{\link[htmlwidgets]{JS}}
+}
+\author{
+Anthony Flores
+}
diff --git a/man/ojo_add_geoid.Rd b/man/ojo_add_geoid.Rd
new file mode 100644
index 0000000..7f73183
--- /dev/null
+++ b/man/ojo_add_geoid.Rd
@@ -0,0 +1,40 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/ojo_add_geoid.R
+\name{ojo_add_geoid}
+\alias{ojo_add_geoid}
+\title{FUNCTION_TITLE}
+\usage{
+ojo_add_geoid(data, geography = c("county", "state"), year = 2019)
+}
+\arguments{
+\item{data}{PARAM_DESCRIPTION}
+
+\item{geography}{PARAM_DESCRIPTION, Default: c("county", "state")}
+
+\item{year}{PARAM_DESCRIPTION, Default: 2019}
+}
+\value{
+OUTPUT_DESCRIPTION
+}
+\description{
+FUNCTION_DESCRIPTION
+}
+\details{
+DETAILS
+}
+\examples{
+\dontrun{
+if(interactive()){
+ #EXAMPLE1
+ }
+}
+}
+\seealso{
+\code{\link[rlang]{is_installed}}
+\code{\link[tidycensus]{get_estimates}}
+\code{\link[dplyr]{mutate}}, \code{\link[dplyr]{select}}, \code{\link[dplyr]{mutate-joins}}
+\code{\link[stringr]{str_remove}}, \code{\link[stringr]{case}}, \code{\link[stringr]{str_replace}}
+}
+\author{
+Anthony Flores
+}
diff --git a/man/ojo_add_geometries.Rd b/man/ojo_add_geometries.Rd
new file mode 100644
index 0000000..d4c6f37
--- /dev/null
+++ b/man/ojo_add_geometries.Rd
@@ -0,0 +1,39 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/ojo_add_geometries.R
+\name{ojo_add_geometries}
+\alias{ojo_add_geometries}
+\title{FUNCTION_TITLE}
+\usage{
+ojo_add_geometries(data, geography = c("county", "state"), ...)
+}
+\arguments{
+\item{data}{PARAM_DESCRIPTION}
+
+\item{geography}{PARAM_DESCRIPTION, Default: c("county", "state")}
+
+\item{...}{PARAM_DESCRIPTION}
+}
+\value{
+OUTPUT_DESCRIPTION
+}
+\description{
+FUNCTION_DESCRIPTION
+}
+\details{
+DETAILS
+}
+\examples{
+\dontrun{
+if(interactive()){
+ #EXAMPLE1
+ }
+}
+}
+\seealso{
+\code{\link[tigris]{counties}}, \code{\link[tigris]{states}}
+\code{\link[dplyr]{select}}, \code{\link[dplyr]{mutate-joins}}, \code{\link[dplyr]{cross_join}}
+\code{\link[stats]{filter}}
+}
+\author{
+Anthony Flores
+}
diff --git a/man/ojo_add_month_and_year.Rd b/man/ojo_add_month_and_year.Rd
new file mode 100644
index 0000000..4113e99
--- /dev/null
+++ b/man/ojo_add_month_and_year.Rd
@@ -0,0 +1,38 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/ojo_add_month_and_year.R
+\name{ojo_add_month_and_year}
+\alias{ojo_add_month_and_year}
+\title{FUNCTION_TITLE}
+\usage{
+ojo_add_month_and_year(data, ...)
+}
+\arguments{
+\item{data}{PARAM_DESCRIPTION}
+
+\item{...}{PARAM_DESCRIPTION}
+}
+\value{
+OUTPUT_DESCRIPTION
+}
+\description{
+FUNCTION_DESCRIPTION
+}
+\details{
+DETAILS
+}
+\examples{
+\dontrun{
+if(interactive()){
+ #EXAMPLE1
+ }
+}
+}
+\seealso{
+\code{\link[rlang]{defusing-advanced}}, \code{\link[rlang]{quo_label}}, \code{\link[rlang]{sym}}
+\code{\link[purrr]{map}}
+\code{\link[dplyr]{mutate}}
+\code{\link[lubridate]{round_date}}
+}
+\author{
+Anthony Flores
+}
diff --git a/man/ojo_add_population.Rd b/man/ojo_add_population.Rd
new file mode 100644
index 0000000..fd00a15
--- /dev/null
+++ b/man/ojo_add_population.Rd
@@ -0,0 +1,51 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/ojo_add_population.R
+\name{ojo_add_population}
+\alias{ojo_add_population}
+\title{FUNCTION_TITLE}
+\usage{
+ojo_add_population(
+ data,
+ geography = c("both", "county", "state"),
+ year_column,
+ individual_year = NA,
+ ...
+)
+}
+\arguments{
+\item{data}{PARAM_DESCRIPTION}
+
+\item{geography}{PARAM_DESCRIPTION, Default: c("both", "county", "state")}
+
+\item{year_column}{PARAM_DESCRIPTION}
+
+\item{individual_year}{PARAM_DESCRIPTION, Default: NA}
+
+\item{...}{PARAM_DESCRIPTION}
+}
+\value{
+OUTPUT_DESCRIPTION
+}
+\description{
+FUNCTION_DESCRIPTION
+}
+\details{
+DETAILS
+}
+\examples{
+\dontrun{
+if(interactive()){
+ #EXAMPLE1
+ }
+}
+}
+\seealso{
+\code{\link[dplyr]{select}}, \code{\link[dplyr]{reexports}}, \code{\link[dplyr]{nth}}, \code{\link[dplyr]{pull}}, \code{\link[dplyr]{mutate}}, \code{\link[dplyr]{bind_rows}}, \code{\link[dplyr]{mutate-joins}}, \code{\link[dplyr]{join_by}}
+\code{\link[lubridate]{year}}, \code{\link[lubridate]{ymd}}
+\code{\link[tidycensus]{get_estimates}}
+\code{\link[stats]{filter}}
+\code{\link[tidyr]{pivot_wider}}
+}
+\author{
+Anthony Flores
+}
diff --git a/man/ojo_aggregate.Rd b/man/ojo_aggregate.Rd
new file mode 100644
index 0000000..a16274e
--- /dev/null
+++ b/man/ojo_aggregate.Rd
@@ -0,0 +1,52 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/ojo_aggregate.R
+\name{ojo_aggregate}
+\alias{ojo_aggregate}
+\title{FUNCTION_TITLE}
+\usage{
+ojo_aggregate(
+ data,
+ ...,
+ group_by,
+ geography = c("county", "state"),
+ rate = 10^3,
+ rate_suffix = "1k"
+)
+}
+\arguments{
+\item{data}{PARAM_DESCRIPTION}
+
+\item{...}{PARAM_DESCRIPTION}
+
+\item{group_by}{PARAM_DESCRIPTION}
+
+\item{geography}{PARAM_DESCRIPTION, Default: c("county", "state")}
+
+\item{rate}{PARAM_DESCRIPTION, Default: 10^3}
+
+\item{rate_suffix}{PARAM_DESCRIPTION, Default: '1k'}
+}
+\value{
+OUTPUT_DESCRIPTION
+}
+\description{
+FUNCTION_DESCRIPTION
+}
+\details{
+DETAILS
+}
+\examples{
+\dontrun{
+if(interactive()){
+ #EXAMPLE1
+ }
+}
+}
+\seealso{
+\code{\link[rlang]{enquo}}, \code{\link[rlang]{quosure-tools}}, \code{\link[rlang]{as_label}}
+\code{\link[purrr]{map}}
+\code{\link[dplyr]{if_else}}, \code{\link[dplyr]{distinct}}, \code{\link[dplyr]{count}}, \code{\link[dplyr]{mutate}}, \code{\link[dplyr]{arrange}}
+}
+\author{
+Anthony Flores
+}
diff --git a/man/ojo_district_and_date_filters.Rd b/man/ojo_district_and_date_filters.Rd
new file mode 100644
index 0000000..dd6351d
--- /dev/null
+++ b/man/ojo_district_and_date_filters.Rd
@@ -0,0 +1,50 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/ojo_district_and_date_filters.R
+\name{ojo_district_and_date_filters}
+\alias{ojo_district_and_date_filters}
+\title{FUNCTION_TITLE}
+\usage{
+ojo_district_and_date_filters(
+ data,
+ districts = "ALL",
+ date_start = NA,
+ date_end = NA,
+ district_variable = "district",
+ date_variable = "date_filed"
+)
+}
+\arguments{
+\item{data}{PARAM_DESCRIPTION}
+
+\item{districts}{PARAM_DESCRIPTION, Default: 'ALL'}
+
+\item{date_start}{PARAM_DESCRIPTION, Default: NA}
+
+\item{date_end}{PARAM_DESCRIPTION, Default: NA}
+
+\item{district_variable}{PARAM_DESCRIPTION, Default: 'district'}
+
+\item{date_variable}{PARAM_DESCRIPTION, Default: 'date_filed'}
+}
+\value{
+OUTPUT_DESCRIPTION
+}
+\description{
+FUNCTION_DESCRIPTION
+}
+\details{
+DETAILS
+}
+\examples{
+\dontrun{
+if(interactive()){
+ #EXAMPLE1
+ }
+}
+}
+\seealso{
+\code{\link[dplyr]{filter}}
+}
+\author{
+Anthony Flores
+}
diff --git a/man/ojo_highchart_map.Rd b/man/ojo_highchart_map.Rd
new file mode 100644
index 0000000..d13e9e8
--- /dev/null
+++ b/man/ojo_highchart_map.Rd
@@ -0,0 +1,58 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/ojo_highchart_map.R
+\name{ojo_highchart_map}
+\alias{ojo_highchart_map}
+\title{FUNCTION_TITLE}
+\usage{
+ojo_highchart_map(
+ data,
+ variable,
+ ...,
+ caption = NULL,
+ nbins,
+ map_color_stops = rev(viridis::magma(n = 3))
+)
+}
+\arguments{
+\item{data}{PARAM_DESCRIPTION}
+
+\item{variable}{PARAM_DESCRIPTION}
+
+\item{...}{PARAM_DESCRIPTION}
+
+\item{caption}{PARAM_DESCRIPTION, Default: NULL}
+
+\item{nbins}{PARAM_DESCRIPTION}
+
+\item{map_color_stops}{PARAM_DESCRIPTION, Default: rev(viridis::magma(n = 3))}
+}
+\value{
+OUTPUT_DESCRIPTION
+}
+\description{
+FUNCTION_DESCRIPTION
+}
+\details{
+DETAILS
+}
+\examples{
+\dontrun{
+if(interactive()){
+ #EXAMPLE1
+ }
+}
+}
+\seealso{
+\code{\link[viridis]{reexports}}
+\code{\link[rlang]{enquo}}, \code{\link[rlang]{as_label}}
+\code{\link[dplyr]{select}}, \code{\link[dplyr]{pull}}, \code{\link[dplyr]{reexports}}
+\code{\link[geojsonsf]{sf_geojson}}
+\code{\link[jsonlite]{toJSON, fromJSON}}
+\code{\link[stats]{na.fail}}
+\code{\link[grDevices]{nclass}}
+\code{\link[graphics]{hist}}
+\code{\link[highcharter]{color_classes}}, \code{\link[highcharter]{color_stops}}, \code{\link[highcharter]{highchart}}, \code{\link[highcharter]{hc_add_series_map}}, \code{\link[highcharter]{hc_caption}}, \code{\link[highcharter]{hc_colorAxis}}, \code{\link[highcharter]{hc_legend}}, \code{\link[highcharter]{hc_mapNavigation}}, \code{\link[highcharter]{hc_add_theme}}
+}
+\author{
+Anthony Flores
+}
diff --git a/man/ojo_optional_filter.Rd b/man/ojo_optional_filter.Rd
new file mode 100644
index 0000000..b3cdb02
--- /dev/null
+++ b/man/ojo_optional_filter.Rd
@@ -0,0 +1,37 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/ojo_optional_filter.R
+\name{ojo_optional_filter}
+\alias{ojo_optional_filter}
+\title{FUNCTION_TITLE}
+\usage{
+ojo_optional_filter(data, variable, variable_values = NA)
+}
+\arguments{
+\item{data}{PARAM_DESCRIPTION}
+
+\item{variable}{PARAM_DESCRIPTION}
+
+\item{variable_values}{PARAM_DESCRIPTION, Default: NA}
+}
+\value{
+OUTPUT_DESCRIPTION
+}
+\description{
+FUNCTION_DESCRIPTION
+}
+\details{
+DETAILS
+}
+\examples{
+\dontrun{
+if(interactive()){
+ #EXAMPLE1
+ }
+}
+}
+\seealso{
+\code{\link[dplyr]{filter}}
+}
+\author{
+Anthony Flores
+}
diff --git a/man/ojo_plot_lines.Rd b/man/ojo_plot_lines.Rd
new file mode 100644
index 0000000..0688b3b
--- /dev/null
+++ b/man/ojo_plot_lines.Rd
@@ -0,0 +1,78 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/ojo_plot_lines.R
+\name{ojo_plot_lines}
+\alias{ojo_plot_lines}
+\title{FUNCTION_TITLE}
+\usage{
+ojo_plot_lines(
+ data,
+ x,
+ y,
+ ...,
+ color_variable = variable,
+ facet_variable = NA,
+ legend_labels = NA,
+ facet_labels = NA,
+ custom_color_palette = NA,
+ number_of_columns = 1,
+ data_to_highlight = NA,
+ highlight_color = "red",
+ theme = custom_ojo_theme(),
+ add_covid_labels = FALSE
+)
+}
+\arguments{
+\item{data}{PARAM_DESCRIPTION}
+
+\item{x}{PARAM_DESCRIPTION}
+
+\item{y}{PARAM_DESCRIPTION}
+
+\item{...}{PARAM_DESCRIPTION}
+
+\item{color_variable}{PARAM_DESCRIPTION, Default: variable}
+
+\item{facet_variable}{PARAM_DESCRIPTION, Default: NA}
+
+\item{legend_labels}{PARAM_DESCRIPTION, Default: NA}
+
+\item{facet_labels}{PARAM_DESCRIPTION, Default: NA}
+
+\item{custom_color_palette}{PARAM_DESCRIPTION, Default: NA}
+
+\item{number_of_columns}{PARAM_DESCRIPTION, Default: 1}
+
+\item{data_to_highlight}{PARAM_DESCRIPTION, Default: NA}
+
+\item{highlight_color}{PARAM_DESCRIPTION, Default: 'red'}
+
+\item{theme}{PARAM_DESCRIPTION, Default: custom_ojo_theme()}
+
+\item{add_covid_labels}{PARAM_DESCRIPTION, Default: FALSE}
+}
+\value{
+OUTPUT_DESCRIPTION
+}
+\description{
+FUNCTION_DESCRIPTION
+}
+\details{
+DETAILS
+}
+\examples{
+\dontrun{
+if(interactive()){
+ #EXAMPLE1
+ }
+}
+}
+\seealso{
+\code{\link[stringr]{str_flatten}}
+\code{\link[dplyr]{if_else}}, \code{\link[dplyr]{select}}, \code{\link[dplyr]{reexports}}, \code{\link[dplyr]{distinct}}, \code{\link[dplyr]{pull}}, \code{\link[dplyr]{summarise}}
+\code{\link[tidyr]{pivot_longer}}
+\code{\link[ggplot2]{ggplot}}, \code{\link[ggplot2]{aes}}, \code{\link[ggplot2]{geom_path}}, \code{\link[ggplot2]{geom_point}}, \code{\link[ggplot2]{facet_wrap}}, \code{\link[ggplot2]{vars}}, \code{\link[ggplot2]{as_labeller}}, \code{\link[ggplot2]{theme}}, \code{\link[ggplot2]{margin}}, \code{\link[ggplot2]{scale_continuous}}, \code{\link[ggplot2]{scale_manual}}, \code{\link[ggplot2]{c("guide_bins", "guide_colourbar", "guide_coloursteps", "guide_legend", "guides", "guides")}}, \code{\link[ggplot2]{guide_legend}}
+\code{\link[scales]{label_number}}
+}
+\author{
+Anthony Flores
+}
diff --git a/man/plumber_api.Rd b/man/plumber_api.Rd
deleted file mode 100644
index 84ef92b..0000000
--- a/man/plumber_api.Rd
+++ /dev/null
@@ -1,18 +0,0 @@
-% Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/hello.R
-\name{plumber_api}
-\alias{plumber_api}
-\title{Personal greeting as a Plumber API}
-\usage{
-plumber_api(...)
-}
-\arguments{
-\item{...}{Additional arguments to plumber::pr_run()}
-}
-\value{
-Plumber API showcasing the personal greeting feature.
-}
-\description{
-Greet a person and appropriately capitalize their name
-as a Plumber API.
-}
diff --git a/man/pretty_variable_names.Rd b/man/pretty_variable_names.Rd
new file mode 100644
index 0000000..ff26694
--- /dev/null
+++ b/man/pretty_variable_names.Rd
@@ -0,0 +1,34 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/pretty_variable_names.R
+\name{pretty_variable_names}
+\alias{pretty_variable_names}
+\title{FUNCTION_TITLE}
+\usage{
+pretty_variable_names(variable_names)
+}
+\arguments{
+\item{variable_names}{PARAM_DESCRIPTION}
+}
+\value{
+OUTPUT_DESCRIPTION
+}
+\description{
+FUNCTION_DESCRIPTION
+}
+\details{
+DETAILS
+}
+\examples{
+\dontrun{
+if(interactive()){
+ #EXAMPLE1
+ }
+}
+}
+\seealso{
+\code{\link[snakecase]{caseconverter}}
+\code{\link[stringr]{str_replace}}
+}
+\author{
+Anthony Flores
+}
diff --git a/man/shiny_app.Rd b/man/shiny_app.Rd
deleted file mode 100644
index 8171c58..0000000
--- a/man/shiny_app.Rd
+++ /dev/null
@@ -1,15 +0,0 @@
-% Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/hello.R
-\name{shiny_app}
-\alias{shiny_app}
-\title{Personal greeting as a Shiny app}
-\usage{
-shiny_app()
-}
-\value{
-Shiny app showcasing the personal greeting feature.
-}
-\description{
-Greet a person and appropriately capitalize their name
-as a Shiny app.
-}
diff --git a/man/tably.Rd b/man/tably.Rd
new file mode 100644
index 0000000..78dfda5
--- /dev/null
+++ b/man/tably.Rd
@@ -0,0 +1,42 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/tably.R
+\name{tably}
+\alias{tably}
+\title{FUNCTION_TITLE}
+\usage{
+tably(data, ..., print_n = NA, top_n = NA, sort = TRUE)
+}
+\arguments{
+\item{data}{PARAM_DESCRIPTION}
+
+\item{...}{PARAM_DESCRIPTION}
+
+\item{print_n}{PARAM_DESCRIPTION, Default: NA}
+
+\item{top_n}{PARAM_DESCRIPTION, Default: NA}
+
+\item{sort}{PARAM_DESCRIPTION, Default: TRUE}
+}
+\value{
+OUTPUT_DESCRIPTION
+}
+\description{
+FUNCTION_DESCRIPTION
+}
+\details{
+DETAILS
+}
+\examples{
+\dontrun{
+if(interactive()){
+ #EXAMPLE1
+ }
+}
+}
+\seealso{
+\code{\link[rlang]{enquo}}, \code{\link[rlang]{sym}}
+\code{\link[dplyr]{count}}, \code{\link[dplyr]{mutate}}, \code{\link[dplyr]{slice}}, \code{\link[dplyr]{summarise}}
+}
+\author{
+Anthony Flores
+}
diff --git a/renv.lock b/renv.lock
new file mode 100644
index 0000000..47243a0
--- /dev/null
+++ b/renv.lock
@@ -0,0 +1,2173 @@
+{
+ "R": {
+ "Version": "4.3.1",
+ "Repositories": [
+ {
+ "Name": "BioCsoft",
+ "URL": "https://bioconductor.org/packages/3.17/bioc"
+ },
+ {
+ "Name": "BioCann",
+ "URL": "https://bioconductor.org/packages/3.17/data/annotation"
+ },
+ {
+ "Name": "BioCexp",
+ "URL": "https://bioconductor.org/packages/3.17/data/experiment"
+ },
+ {
+ "Name": "BioCworkflows",
+ "URL": "https://bioconductor.org/packages/3.17/workflows"
+ },
+ {
+ "Name": "BioCbooks",
+ "URL": "https://bioconductor.org/packages/3.17/books"
+ },
+ {
+ "Name": "CRAN",
+ "URL": "https://packagemanager.posit.co/cran/latest"
+ }
+ ]
+ },
+ "Bioconductor": {
+ "Version": "3.17"
+ },
+ "Packages": {
+ "BiocManager": {
+ "Package": "BiocManager",
+ "Version": "1.30.22",
+ "Source": "Repository",
+ "Repository": "RSPM",
+ "Requirements": [
+ "utils"
+ ],
+ "Hash": "d57e43105a1aa9cb54fdb4629725acb1"
+ },
+ "BiocVersion": {
+ "Package": "BiocVersion",
+ "Version": "3.17.1",
+ "Source": "Bioconductor",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "f7c0d5521799b7b0d0a211143ed0bfcb"
+ },
+ "DBI": {
+ "Package": "DBI",
+ "Version": "1.1.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "methods"
+ ],
+ "Hash": "b2866e62bab9378c3cc9476a1954226b"
+ },
+ "KernSmooth": {
+ "Package": "KernSmooth",
+ "Version": "2.23-22",
+ "Source": "Repository",
+ "Repository": "RSPM",
+ "Requirements": [
+ "R",
+ "stats"
+ ],
+ "Hash": "2fecebc3047322fa5930f74fae5de70f"
+ },
+ "MASS": {
+ "Package": "MASS",
+ "Version": "7.3-60",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "grDevices",
+ "graphics",
+ "methods",
+ "stats",
+ "utils"
+ ],
+ "Hash": "a56a6365b3fa73293ea8d084be0d9bb0"
+ },
+ "Matrix": {
+ "Package": "Matrix",
+ "Version": "1.6-0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "grDevices",
+ "graphics",
+ "grid",
+ "lattice",
+ "methods",
+ "stats",
+ "utils"
+ ],
+ "Hash": "31262fd18481fab05c5e7258dac163ca"
+ },
+ "R6": {
+ "Package": "R6",
+ "Version": "2.5.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "470851b6d5d0ac559e9d01bb352b4021"
+ },
+ "RColorBrewer": {
+ "Package": "RColorBrewer",
+ "Version": "1.1-3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "45f0398006e83a5b10b72a90663d8d8c"
+ },
+ "Rcpp": {
+ "Package": "Rcpp",
+ "Version": "1.0.11",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "methods",
+ "utils"
+ ],
+ "Hash": "ae6cbbe1492f4de79c45fce06f967ce8"
+ },
+ "TTR": {
+ "Package": "TTR",
+ "Version": "0.24.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "curl",
+ "xts",
+ "zoo"
+ ],
+ "Hash": "c553a7be22ec50faaebee27be54a1313"
+ },
+ "XML": {
+ "Package": "XML",
+ "Version": "3.99-0.14",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "methods",
+ "utils"
+ ],
+ "Hash": "e5c8af79df616c135b21eaeb1dc6bc5c"
+ },
+ "askpass": {
+ "Package": "askpass",
+ "Version": "1.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "sys"
+ ],
+ "Hash": "e8a22846fff485f0be3770c2da758713"
+ },
+ "assertthat": {
+ "Package": "assertthat",
+ "Version": "0.2.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "tools"
+ ],
+ "Hash": "50c838a310445e954bc13f26f26a6ecf"
+ },
+ "backports": {
+ "Package": "backports",
+ "Version": "1.4.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "c39fbec8a30d23e721980b8afb31984c"
+ },
+ "base64enc": {
+ "Package": "base64enc",
+ "Version": "0.1-3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "543776ae6848fde2f48ff3816d0628bc"
+ },
+ "bit": {
+ "Package": "bit",
+ "Version": "4.0.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "d242abec29412ce988848d0294b208fd"
+ },
+ "bit64": {
+ "Package": "bit64",
+ "Version": "4.0.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "bit",
+ "methods",
+ "stats",
+ "utils"
+ ],
+ "Hash": "9fe98599ca456d6552421db0d6772d8f"
+ },
+ "brio": {
+ "Package": "brio",
+ "Version": "1.1.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "976cf154dfb043c012d87cddd8bca363"
+ },
+ "broom": {
+ "Package": "broom",
+ "Version": "1.0.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "backports",
+ "dplyr",
+ "ellipsis",
+ "generics",
+ "glue",
+ "lifecycle",
+ "purrr",
+ "rlang",
+ "stringr",
+ "tibble",
+ "tidyr"
+ ],
+ "Hash": "fd25391c3c4f6ecf0fa95f1e6d15378c"
+ },
+ "bslib": {
+ "Package": "bslib",
+ "Version": "0.5.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "base64enc",
+ "cachem",
+ "grDevices",
+ "htmltools",
+ "jquerylib",
+ "jsonlite",
+ "memoise",
+ "mime",
+ "rlang",
+ "sass"
+ ],
+ "Hash": "1b117970533deb6d4e992c1b34e9d905"
+ },
+ "cachem": {
+ "Package": "cachem",
+ "Version": "1.0.8",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "fastmap",
+ "rlang"
+ ],
+ "Hash": "c35768291560ce302c0a6589f92e837d"
+ },
+ "callr": {
+ "Package": "callr",
+ "Version": "3.7.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "R6",
+ "processx",
+ "utils"
+ ],
+ "Hash": "9b2191ede20fa29828139b9900922e51"
+ },
+ "class": {
+ "Package": "class",
+ "Version": "7.3-22",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "MASS",
+ "R",
+ "stats",
+ "utils"
+ ],
+ "Hash": "f91f6b29f38b8c280f2b9477787d4bb2"
+ },
+ "classInt": {
+ "Package": "classInt",
+ "Version": "0.4-9",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "KernSmooth",
+ "R",
+ "class",
+ "e1071",
+ "grDevices",
+ "graphics",
+ "stats"
+ ],
+ "Hash": "bee651a42a89633eccb36dca9d9ab413"
+ },
+ "cli": {
+ "Package": "cli",
+ "Version": "3.6.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "utils"
+ ],
+ "Hash": "89e6d8219950eac806ae0c489052048a"
+ },
+ "clipr": {
+ "Package": "clipr",
+ "Version": "0.8.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "utils"
+ ],
+ "Hash": "3f038e5ac7f41d4ac41ce658c85e3042"
+ },
+ "codetools": {
+ "Package": "codetools",
+ "Version": "0.2-19",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "c089a619a7fae175d149d89164f8c7d8"
+ },
+ "colorspace": {
+ "Package": "colorspace",
+ "Version": "2.1-0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "grDevices",
+ "graphics",
+ "methods",
+ "stats"
+ ],
+ "Hash": "f20c47fd52fae58b4e377c37bb8c335b"
+ },
+ "commonmark": {
+ "Package": "commonmark",
+ "Version": "1.9.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "d691c61bff84bd63c383874d2d0c3307"
+ },
+ "cpp11": {
+ "Package": "cpp11",
+ "Version": "0.4.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "f07821e9b0aada6c999d4692e22a2ea7"
+ },
+ "crayon": {
+ "Package": "crayon",
+ "Version": "1.5.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "grDevices",
+ "methods",
+ "utils"
+ ],
+ "Hash": "e8a1e41acf02548751f45c718d55aa6a"
+ },
+ "curl": {
+ "Package": "curl",
+ "Version": "5.0.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "2118af9cb164c8d2dddc7b89eaf732d9"
+ },
+ "data.table": {
+ "Package": "data.table",
+ "Version": "1.14.8",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "methods"
+ ],
+ "Hash": "b4c06e554f33344e044ccd7fdca750a9"
+ },
+ "debugme": {
+ "Package": "debugme",
+ "Version": "1.1.0",
+ "Source": "Repository",
+ "Repository": "RSPM",
+ "Requirements": [
+ "crayon",
+ "grDevices"
+ ],
+ "Hash": "2d8a9e4f08f3dd669cb8ddd1eb575959"
+ },
+ "desc": {
+ "Package": "desc",
+ "Version": "1.4.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "R6",
+ "cli",
+ "rprojroot",
+ "utils"
+ ],
+ "Hash": "6b9602c7ebbe87101a9c8edb6e8b6d21"
+ },
+ "diffobj": {
+ "Package": "diffobj",
+ "Version": "0.3.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "crayon",
+ "methods",
+ "stats",
+ "tools",
+ "utils"
+ ],
+ "Hash": "bcaa8b95f8d7d01a5dedfd959ce88ab8"
+ },
+ "digest": {
+ "Package": "digest",
+ "Version": "0.6.33",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "utils"
+ ],
+ "Hash": "b18a9cf3c003977b0cc49d5e76ebe48d"
+ },
+ "downlit": {
+ "Package": "downlit",
+ "Version": "0.4.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "brio",
+ "desc",
+ "digest",
+ "evaluate",
+ "fansi",
+ "memoise",
+ "rlang",
+ "vctrs",
+ "withr",
+ "yaml"
+ ],
+ "Hash": "14fa1f248b60ed67e1f5418391a17b14"
+ },
+ "dplyr": {
+ "Package": "dplyr",
+ "Version": "1.1.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "R6",
+ "cli",
+ "generics",
+ "glue",
+ "lifecycle",
+ "magrittr",
+ "methods",
+ "pillar",
+ "rlang",
+ "tibble",
+ "tidyselect",
+ "utils",
+ "vctrs"
+ ],
+ "Hash": "dea6970ff715ca541c387de363ff405e"
+ },
+ "e1071": {
+ "Package": "e1071",
+ "Version": "1.7-13",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "class",
+ "grDevices",
+ "graphics",
+ "methods",
+ "proxy",
+ "stats",
+ "utils"
+ ],
+ "Hash": "1046cb48d06cb40c2900d8878f03a0fe"
+ },
+ "ellipsis": {
+ "Package": "ellipsis",
+ "Version": "0.3.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "rlang"
+ ],
+ "Hash": "bb0eec2fe32e88d9e2836c2f73ea2077"
+ },
+ "evaluate": {
+ "Package": "evaluate",
+ "Version": "0.21",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "methods"
+ ],
+ "Hash": "d59f3b464e8da1aef82dc04b588b8dfb"
+ },
+ "fansi": {
+ "Package": "fansi",
+ "Version": "1.0.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "grDevices",
+ "utils"
+ ],
+ "Hash": "1d9e7ad3c8312a192dea7d3db0274fde"
+ },
+ "farver": {
+ "Package": "farver",
+ "Version": "2.1.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "8106d78941f34855c440ddb946b8f7a5"
+ },
+ "fastmap": {
+ "Package": "fastmap",
+ "Version": "1.1.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "f7736a18de97dea803bde0a2daaafb27"
+ },
+ "fontawesome": {
+ "Package": "fontawesome",
+ "Version": "0.5.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "htmltools",
+ "rlang"
+ ],
+ "Hash": "1e22b8cabbad1eae951a75e9f8b52378"
+ },
+ "fs": {
+ "Package": "fs",
+ "Version": "1.6.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "methods"
+ ],
+ "Hash": "47b5f30c720c23999b913a1a635cf0bb"
+ },
+ "future": {
+ "Package": "future",
+ "Version": "1.33.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "digest",
+ "globals",
+ "listenv",
+ "parallel",
+ "parallelly",
+ "utils"
+ ],
+ "Hash": "8e92c7bc53e91b9bb1faf9a6ef0e8514"
+ },
+ "generics": {
+ "Package": "generics",
+ "Version": "0.1.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "methods"
+ ],
+ "Hash": "15e9634c0fcd294799e9b2e929ed1b86"
+ },
+ "geojsonsf": {
+ "Package": "geojsonsf",
+ "Version": "2.0.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "Rcpp",
+ "geometries",
+ "jsonify",
+ "rapidjsonr",
+ "sfheaders"
+ ],
+ "Hash": "8d077646c6713838233e8710910ef92e"
+ },
+ "geometries": {
+ "Package": "geometries",
+ "Version": "0.2.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "Rcpp"
+ ],
+ "Hash": "122e8341ead01f3746dd312ecc5ffd28"
+ },
+ "ggplot2": {
+ "Package": "ggplot2",
+ "Version": "3.4.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "MASS",
+ "R",
+ "cli",
+ "glue",
+ "grDevices",
+ "grid",
+ "gtable",
+ "isoband",
+ "lifecycle",
+ "mgcv",
+ "rlang",
+ "scales",
+ "stats",
+ "tibble",
+ "vctrs",
+ "withr"
+ ],
+ "Hash": "3a147ee02e85a8941aad9909f1b43b7b"
+ },
+ "globals": {
+ "Package": "globals",
+ "Version": "0.16.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "codetools"
+ ],
+ "Hash": "baa9585ab4ce47a9f4618e671778cc6f"
+ },
+ "glue": {
+ "Package": "glue",
+ "Version": "1.6.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "methods"
+ ],
+ "Hash": "4f2596dfb05dac67b9dc558e5c6fba2e"
+ },
+ "gridExtra": {
+ "Package": "gridExtra",
+ "Version": "2.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "grDevices",
+ "graphics",
+ "grid",
+ "gtable",
+ "utils"
+ ],
+ "Hash": "7d7f283939f563670a697165b2cf5560"
+ },
+ "gtable": {
+ "Package": "gtable",
+ "Version": "0.3.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cli",
+ "glue",
+ "grid",
+ "lifecycle",
+ "rlang"
+ ],
+ "Hash": "b44addadb528a0d227794121c00572a0"
+ },
+ "highcharter": {
+ "Package": "highcharter",
+ "Version": "0.9.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "assertthat",
+ "broom",
+ "dplyr",
+ "htmltools",
+ "htmlwidgets",
+ "igraph",
+ "jsonlite",
+ "lubridate",
+ "magrittr",
+ "purrr",
+ "quantmod",
+ "rjson",
+ "rlang",
+ "rlist",
+ "stringr",
+ "tibble",
+ "tidyr",
+ "xts",
+ "yaml",
+ "zoo"
+ ],
+ "Hash": "e9851999ff5a7d33d6b17a68b2cb7f59"
+ },
+ "highr": {
+ "Package": "highr",
+ "Version": "0.10",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "xfun"
+ ],
+ "Hash": "06230136b2d2b9ba5805e1963fa6e890"
+ },
+ "hms": {
+ "Package": "hms",
+ "Version": "1.1.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "lifecycle",
+ "methods",
+ "pkgconfig",
+ "rlang",
+ "vctrs"
+ ],
+ "Hash": "b59377caa7ed00fa41808342002138f9"
+ },
+ "htmltools": {
+ "Package": "htmltools",
+ "Version": "0.5.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "base64enc",
+ "digest",
+ "ellipsis",
+ "fastmap",
+ "grDevices",
+ "rlang",
+ "utils"
+ ],
+ "Hash": "ba0240784ad50a62165058a27459304a"
+ },
+ "htmlwidgets": {
+ "Package": "htmlwidgets",
+ "Version": "1.6.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "grDevices",
+ "htmltools",
+ "jsonlite",
+ "knitr",
+ "rmarkdown",
+ "yaml"
+ ],
+ "Hash": "a865aa85bcb2697f47505bfd70422471"
+ },
+ "httpuv": {
+ "Package": "httpuv",
+ "Version": "1.6.11",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "R6",
+ "Rcpp",
+ "later",
+ "promises",
+ "utils"
+ ],
+ "Hash": "838602f54e32c1a0f8cc80708cefcefa"
+ },
+ "httr": {
+ "Package": "httr",
+ "Version": "1.4.6",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "R6",
+ "curl",
+ "jsonlite",
+ "mime",
+ "openssl"
+ ],
+ "Hash": "7e5e3cbd2a7bc07880c94e22348fb661"
+ },
+ "igraph": {
+ "Package": "igraph",
+ "Version": "1.5.0.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "Matrix",
+ "R",
+ "cli",
+ "cpp11",
+ "grDevices",
+ "graphics",
+ "magrittr",
+ "methods",
+ "pkgconfig",
+ "rlang",
+ "stats",
+ "utils"
+ ],
+ "Hash": "08352b502db2eae1e46364de6e6421f4"
+ },
+ "isoband": {
+ "Package": "isoband",
+ "Version": "0.2.7",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "grid",
+ "utils"
+ ],
+ "Hash": "0080607b4a1a7b28979aecef976d8bc2"
+ },
+ "jquerylib": {
+ "Package": "jquerylib",
+ "Version": "0.1.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "htmltools"
+ ],
+ "Hash": "5aab57a3bd297eee1c1d862735972182"
+ },
+ "jsonify": {
+ "Package": "jsonify",
+ "Version": "1.2.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "Rcpp",
+ "rapidjsonr"
+ ],
+ "Hash": "49a9775e4f8c96c654b6018739067055"
+ },
+ "jsonlite": {
+ "Package": "jsonlite",
+ "Version": "1.8.7",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "methods"
+ ],
+ "Hash": "266a20443ca13c65688b2116d5220f76"
+ },
+ "knitr": {
+ "Package": "knitr",
+ "Version": "1.43",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "evaluate",
+ "highr",
+ "methods",
+ "tools",
+ "xfun",
+ "yaml"
+ ],
+ "Hash": "9775eb076713f627c07ce41d8199d8f6"
+ },
+ "labeling": {
+ "Package": "labeling",
+ "Version": "0.4.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "graphics",
+ "stats"
+ ],
+ "Hash": "3d5108641f47470611a32d0bdf357a72"
+ },
+ "later": {
+ "Package": "later",
+ "Version": "1.3.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "Rcpp",
+ "rlang"
+ ],
+ "Hash": "40401c9cf2bc2259dfe83311c9384710"
+ },
+ "lattice": {
+ "Package": "lattice",
+ "Version": "0.21-8",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "grDevices",
+ "graphics",
+ "grid",
+ "stats",
+ "utils"
+ ],
+ "Hash": "0b8a6d63c8770f02a8b5635f3c431e6b"
+ },
+ "lifecycle": {
+ "Package": "lifecycle",
+ "Version": "1.0.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cli",
+ "glue",
+ "rlang"
+ ],
+ "Hash": "001cecbeac1cff9301bdc3775ee46a86"
+ },
+ "listenv": {
+ "Package": "listenv",
+ "Version": "0.9.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "4fbd3679ec8ee169ba28d4b1ea7d0e8f"
+ },
+ "lubridate": {
+ "Package": "lubridate",
+ "Version": "1.9.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "generics",
+ "methods",
+ "timechange"
+ ],
+ "Hash": "e25f18436e3efd42c7c590a1c4c15390"
+ },
+ "magrittr": {
+ "Package": "magrittr",
+ "Version": "2.0.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "7ce2733a9826b3aeb1775d56fd305472"
+ },
+ "memoise": {
+ "Package": "memoise",
+ "Version": "2.0.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "cachem",
+ "rlang"
+ ],
+ "Hash": "e2817ccf4a065c5d9d7f2cfbe7c1d78c"
+ },
+ "mgcv": {
+ "Package": "mgcv",
+ "Version": "1.9-0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "Matrix",
+ "R",
+ "graphics",
+ "methods",
+ "nlme",
+ "splines",
+ "stats",
+ "utils"
+ ],
+ "Hash": "086028ca0460d0c368028d3bda58f31b"
+ },
+ "mime": {
+ "Package": "mime",
+ "Version": "0.12",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "tools"
+ ],
+ "Hash": "18e9c28c1d3ca1560ce30658b22ce104"
+ },
+ "munsell": {
+ "Package": "munsell",
+ "Version": "0.5.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "colorspace",
+ "methods"
+ ],
+ "Hash": "6dfe8bf774944bd5595785e3229d8771"
+ },
+ "nlme": {
+ "Package": "nlme",
+ "Version": "3.1-162",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "graphics",
+ "lattice",
+ "stats",
+ "utils"
+ ],
+ "Hash": "0984ce8da8da9ead8643c5cbbb60f83e"
+ },
+ "openssl": {
+ "Package": "openssl",
+ "Version": "2.1.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "askpass"
+ ],
+ "Hash": "273a6bb4a9844c296a459d2176673270"
+ },
+ "parallelly": {
+ "Package": "parallelly",
+ "Version": "1.36.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "parallel",
+ "tools",
+ "utils"
+ ],
+ "Hash": "bca377e1c87ec89ebed77bba00635b2e"
+ },
+ "parsedate": {
+ "Package": "parsedate",
+ "Version": "1.3.1",
+ "Source": "Repository",
+ "Repository": "RSPM",
+ "Hash": "7f5024cc7af45eeecef657fa62beb568"
+ },
+ "pillar": {
+ "Package": "pillar",
+ "Version": "1.9.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "cli",
+ "fansi",
+ "glue",
+ "lifecycle",
+ "rlang",
+ "utf8",
+ "utils",
+ "vctrs"
+ ],
+ "Hash": "15da5a8412f317beeee6175fbc76f4bb"
+ },
+ "pingr": {
+ "Package": "pingr",
+ "Version": "2.0.2",
+ "Source": "Repository",
+ "Repository": "RSPM",
+ "Requirements": [
+ "processx",
+ "utils"
+ ],
+ "Hash": "b762f8f7d305f7eb0bab96eb1a3c782a"
+ },
+ "pkgconfig": {
+ "Package": "pkgconfig",
+ "Version": "2.0.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "utils"
+ ],
+ "Hash": "01f28d4278f15c76cddbea05899c5d6f"
+ },
+ "pkgdown": {
+ "Package": "pkgdown",
+ "Version": "2.0.7",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "bslib",
+ "callr",
+ "cli",
+ "desc",
+ "digest",
+ "downlit",
+ "fs",
+ "httr",
+ "jsonlite",
+ "magrittr",
+ "memoise",
+ "purrr",
+ "ragg",
+ "rlang",
+ "rmarkdown",
+ "tibble",
+ "whisker",
+ "withr",
+ "xml2",
+ "yaml"
+ ],
+ "Hash": "16fa15449c930bf3a7761d3c68f8abf9"
+ },
+ "pkgload": {
+ "Package": "pkgload",
+ "Version": "1.3.2.1",
+ "Source": "Repository",
+ "Repository": "RSPM",
+ "Requirements": [
+ "R",
+ "cli",
+ "crayon",
+ "desc",
+ "fs",
+ "glue",
+ "methods",
+ "rlang",
+ "rprojroot",
+ "utils",
+ "withr"
+ ],
+ "Hash": "a7f498a1b2a4a6816148e498509f6e1d"
+ },
+ "plumber": {
+ "Package": "plumber",
+ "Version": "1.2.1",
+ "Source": "Repository",
+ "Repository": "RSPM",
+ "Requirements": [
+ "R",
+ "R6",
+ "crayon",
+ "ellipsis",
+ "httpuv",
+ "jsonlite",
+ "lifecycle",
+ "magrittr",
+ "mime",
+ "promises",
+ "rlang",
+ "sodium",
+ "stringi",
+ "swagger",
+ "webutils"
+ ],
+ "Hash": "8b65a7a00ef8edc5ddc6fabf0aff1194"
+ },
+ "png": {
+ "Package": "png",
+ "Version": "0.1-8",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "bd54ba8a0a5faded999a7aab6e46b374"
+ },
+ "praise": {
+ "Package": "praise",
+ "Version": "1.0.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "a555924add98c99d2f411e37e7d25e9f"
+ },
+ "prettyunits": {
+ "Package": "prettyunits",
+ "Version": "1.1.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "95ef9167b75dde9d2ccc3c7528393e7e"
+ },
+ "processx": {
+ "Package": "processx",
+ "Version": "3.8.2",
+ "Source": "Repository",
+ "Repository": "RSPM",
+ "Requirements": [
+ "R",
+ "R6",
+ "ps",
+ "utils"
+ ],
+ "Hash": "3efbd8ac1be0296a46c55387aeace0f3"
+ },
+ "progress": {
+ "Package": "progress",
+ "Version": "1.2.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R6",
+ "crayon",
+ "hms",
+ "prettyunits"
+ ],
+ "Hash": "14dc9f7a3c91ebb14ec5bb9208a07061"
+ },
+ "promises": {
+ "Package": "promises",
+ "Version": "1.2.0.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R6",
+ "Rcpp",
+ "later",
+ "magrittr",
+ "rlang",
+ "stats"
+ ],
+ "Hash": "4ab2c43adb4d4699cf3690acd378d75d"
+ },
+ "proxy": {
+ "Package": "proxy",
+ "Version": "0.4-27",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "stats",
+ "utils"
+ ],
+ "Hash": "e0ef355c12942cf7a6b91a6cfaea8b3e"
+ },
+ "ps": {
+ "Package": "ps",
+ "Version": "1.7.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "utils"
+ ],
+ "Hash": "709d852d33178db54b17c722e5b1e594"
+ },
+ "purrr": {
+ "Package": "purrr",
+ "Version": "1.0.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cli",
+ "lifecycle",
+ "magrittr",
+ "rlang",
+ "vctrs"
+ ],
+ "Hash": "d71c815267c640f17ddbf7f16144b4bb"
+ },
+ "quantmod": {
+ "Package": "quantmod",
+ "Version": "0.4.24",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "TTR",
+ "curl",
+ "jsonlite",
+ "methods",
+ "xts",
+ "zoo"
+ ],
+ "Hash": "e505db321b45813cca561521092b89bc"
+ },
+ "ragg": {
+ "Package": "ragg",
+ "Version": "1.2.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "systemfonts",
+ "textshaping"
+ ],
+ "Hash": "690bc058ea2b1b8a407d3cfe3dce3ef9"
+ },
+ "rapidjsonr": {
+ "Package": "rapidjsonr",
+ "Version": "1.2.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "88b9f48c93d17cdb811b54079a6a414f"
+ },
+ "rappdirs": {
+ "Package": "rappdirs",
+ "Version": "0.3.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "5e3c5dc0b071b21fa128676560dbe94d"
+ },
+ "readr": {
+ "Package": "readr",
+ "Version": "2.1.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "R6",
+ "cli",
+ "clipr",
+ "cpp11",
+ "crayon",
+ "hms",
+ "lifecycle",
+ "methods",
+ "rlang",
+ "tibble",
+ "tzdb",
+ "utils",
+ "vroom"
+ ],
+ "Hash": "b5047343b3825f37ad9d3b5d89aa1078"
+ },
+ "rematch": {
+ "Package": "rematch",
+ "Version": "2.0.0",
+ "Source": "Repository",
+ "Repository": "RSPM",
+ "Hash": "cbff1b666c6fa6d21202f07e2318d4f1"
+ },
+ "rematch2": {
+ "Package": "rematch2",
+ "Version": "2.1.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "tibble"
+ ],
+ "Hash": "76c9e04c712a05848ae7a23d2f170a40"
+ },
+ "renv": {
+ "Package": "renv",
+ "Version": "1.0.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "utils"
+ ],
+ "Hash": "c321cd99d56443dbffd1c9e673c0c1a2"
+ },
+ "rjson": {
+ "Package": "rjson",
+ "Version": "0.2.21",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "f9da75e6444e95a1baf8ca24909d63b9"
+ },
+ "rlang": {
+ "Package": "rlang",
+ "Version": "1.1.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "utils"
+ ],
+ "Hash": "a85c767b55f0bf9b7ad16c6d7baee5bb"
+ },
+ "rlist": {
+ "Package": "rlist",
+ "Version": "0.4.6.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "XML",
+ "data.table",
+ "jsonlite",
+ "yaml"
+ ],
+ "Hash": "290c8ea0700d2e7258082d0025386e68"
+ },
+ "rmarkdown": {
+ "Package": "rmarkdown",
+ "Version": "2.23",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "bslib",
+ "evaluate",
+ "fontawesome",
+ "htmltools",
+ "jquerylib",
+ "jsonlite",
+ "knitr",
+ "methods",
+ "stringr",
+ "tinytex",
+ "tools",
+ "utils",
+ "xfun",
+ "yaml"
+ ],
+ "Hash": "79f14e53725f28900d936f692bfdd69f"
+ },
+ "rprojroot": {
+ "Package": "rprojroot",
+ "Version": "2.0.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "1de7ab598047a87bba48434ba35d497d"
+ },
+ "rstudioapi": {
+ "Package": "rstudioapi",
+ "Version": "0.15.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "5564500e25cffad9e22244ced1379887"
+ },
+ "rvest": {
+ "Package": "rvest",
+ "Version": "1.0.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cli",
+ "glue",
+ "httr",
+ "lifecycle",
+ "magrittr",
+ "rlang",
+ "selectr",
+ "tibble",
+ "withr",
+ "xml2"
+ ],
+ "Hash": "a4a5ac819a467808c60e36e92ddf195e"
+ },
+ "s2": {
+ "Package": "s2",
+ "Version": "1.1.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "Rcpp",
+ "wk"
+ ],
+ "Hash": "f1cbe03bb3346f8e817518ffa20f9f5a"
+ },
+ "sass": {
+ "Package": "sass",
+ "Version": "0.4.7",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R6",
+ "fs",
+ "htmltools",
+ "rappdirs",
+ "rlang"
+ ],
+ "Hash": "6bd4d33b50ff927191ec9acbf52fd056"
+ },
+ "scales": {
+ "Package": "scales",
+ "Version": "1.2.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "R6",
+ "RColorBrewer",
+ "farver",
+ "labeling",
+ "lifecycle",
+ "munsell",
+ "rlang",
+ "viridisLite"
+ ],
+ "Hash": "906cb23d2f1c5680b8ce439b44c6fa63"
+ },
+ "selectr": {
+ "Package": "selectr",
+ "Version": "0.4-2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "R6",
+ "methods",
+ "stringr"
+ ],
+ "Hash": "3838071b66e0c566d55cc26bd6e27bf4"
+ },
+ "sf": {
+ "Package": "sf",
+ "Version": "1.0-14",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "DBI",
+ "R",
+ "Rcpp",
+ "classInt",
+ "grDevices",
+ "graphics",
+ "grid",
+ "magrittr",
+ "methods",
+ "s2",
+ "stats",
+ "tools",
+ "units",
+ "utils"
+ ],
+ "Hash": "e2111252a76984ca50bf8d6314348681"
+ },
+ "sfheaders": {
+ "Package": "sfheaders",
+ "Version": "0.4.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "Rcpp",
+ "geometries"
+ ],
+ "Hash": "0b0a55852e87b8f8478efb505eba2ebe"
+ },
+ "shiny": {
+ "Package": "shiny",
+ "Version": "1.7.5",
+ "Source": "Repository",
+ "Repository": "RSPM",
+ "Requirements": [
+ "R",
+ "R6",
+ "bslib",
+ "cachem",
+ "commonmark",
+ "crayon",
+ "ellipsis",
+ "fastmap",
+ "fontawesome",
+ "glue",
+ "grDevices",
+ "htmltools",
+ "httpuv",
+ "jsonlite",
+ "later",
+ "lifecycle",
+ "methods",
+ "mime",
+ "promises",
+ "rlang",
+ "sourcetools",
+ "tools",
+ "utils",
+ "withr",
+ "xtable"
+ ],
+ "Hash": "438b99792adbe82a8329ad8697d45afe"
+ },
+ "shinytest": {
+ "Package": "shinytest",
+ "Version": "1.5.3",
+ "Source": "Repository",
+ "Repository": "RSPM",
+ "Requirements": [
+ "R6",
+ "assertthat",
+ "callr",
+ "crayon",
+ "debugme",
+ "digest",
+ "htmlwidgets",
+ "httpuv",
+ "httr",
+ "jsonlite",
+ "parsedate",
+ "pingr",
+ "rematch",
+ "rlang",
+ "rstudioapi",
+ "shiny",
+ "testthat",
+ "utils",
+ "webdriver",
+ "withr"
+ ],
+ "Hash": "981229915650258e38ae95947210082d"
+ },
+ "showimage": {
+ "Package": "showimage",
+ "Version": "1.0.0",
+ "Source": "Repository",
+ "Repository": "RSPM",
+ "Requirements": [
+ "png",
+ "tools"
+ ],
+ "Hash": "841927b226db842d24d9c288c99ed27b"
+ },
+ "snakecase": {
+ "Package": "snakecase",
+ "Version": "0.11.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "stringi",
+ "stringr"
+ ],
+ "Hash": "4079070fc210c7901c0832a3aeab894f"
+ },
+ "sodium": {
+ "Package": "sodium",
+ "Version": "1.3.0",
+ "Source": "Repository",
+ "Repository": "RSPM",
+ "Hash": "bd436c1e48dc1982125e4d955017724e"
+ },
+ "sourcetools": {
+ "Package": "sourcetools",
+ "Version": "0.1.7-1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "5f5a7629f956619d519205ec475fe647"
+ },
+ "stringi": {
+ "Package": "stringi",
+ "Version": "1.7.12",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "stats",
+ "tools",
+ "utils"
+ ],
+ "Hash": "ca8bd84263c77310739d2cf64d84d7c9"
+ },
+ "stringr": {
+ "Package": "stringr",
+ "Version": "1.5.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cli",
+ "glue",
+ "lifecycle",
+ "magrittr",
+ "rlang",
+ "stringi",
+ "vctrs"
+ ],
+ "Hash": "671a4d384ae9d32fc47a14e98bfa3dc8"
+ },
+ "swagger": {
+ "Package": "swagger",
+ "Version": "3.33.1",
+ "Source": "Repository",
+ "Repository": "RSPM",
+ "Hash": "f28d25ed70c903922254157c11b0081d"
+ },
+ "sys": {
+ "Package": "sys",
+ "Version": "3.4.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "3a1be13d68d47a8cd0bfd74739ca1555"
+ },
+ "systemfonts": {
+ "Package": "systemfonts",
+ "Version": "1.0.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cpp11"
+ ],
+ "Hash": "90b28393209827327de889f49935140a"
+ },
+ "testthat": {
+ "Package": "testthat",
+ "Version": "3.1.10",
+ "Source": "Repository",
+ "Repository": "RSPM",
+ "Requirements": [
+ "R",
+ "R6",
+ "brio",
+ "callr",
+ "cli",
+ "desc",
+ "digest",
+ "ellipsis",
+ "evaluate",
+ "jsonlite",
+ "lifecycle",
+ "magrittr",
+ "methods",
+ "pkgload",
+ "praise",
+ "processx",
+ "ps",
+ "rlang",
+ "utils",
+ "waldo",
+ "withr"
+ ],
+ "Hash": "6f403dc49295610a3a67ea1a9ca64346"
+ },
+ "textshaping": {
+ "Package": "textshaping",
+ "Version": "0.3.6",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cpp11",
+ "systemfonts"
+ ],
+ "Hash": "1ab6223d3670fac7143202cb6a2d43d5"
+ },
+ "tibble": {
+ "Package": "tibble",
+ "Version": "3.2.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "fansi",
+ "lifecycle",
+ "magrittr",
+ "methods",
+ "pillar",
+ "pkgconfig",
+ "rlang",
+ "utils",
+ "vctrs"
+ ],
+ "Hash": "a84e2cc86d07289b3b6f5069df7a004c"
+ },
+ "tidycensus": {
+ "Package": "tidycensus",
+ "Version": "1.4.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "crayon",
+ "dplyr",
+ "httr",
+ "jsonlite",
+ "purrr",
+ "rappdirs",
+ "readr",
+ "rlang",
+ "rvest",
+ "sf",
+ "stringr",
+ "tidyr",
+ "tidyselect",
+ "tigris",
+ "units",
+ "utils",
+ "xml2"
+ ],
+ "Hash": "580d84464cc1b1a07221b171e5f95de5"
+ },
+ "tidyr": {
+ "Package": "tidyr",
+ "Version": "1.3.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cli",
+ "cpp11",
+ "dplyr",
+ "glue",
+ "lifecycle",
+ "magrittr",
+ "purrr",
+ "rlang",
+ "stringr",
+ "tibble",
+ "tidyselect",
+ "utils",
+ "vctrs"
+ ],
+ "Hash": "e47debdc7ce599b070c8e78e8ac0cfcf"
+ },
+ "tidyselect": {
+ "Package": "tidyselect",
+ "Version": "1.2.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cli",
+ "glue",
+ "lifecycle",
+ "rlang",
+ "vctrs",
+ "withr"
+ ],
+ "Hash": "79540e5fcd9e0435af547d885f184fd5"
+ },
+ "tigris": {
+ "Package": "tigris",
+ "Version": "2.0.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "dplyr",
+ "httr",
+ "magrittr",
+ "methods",
+ "rappdirs",
+ "sf",
+ "stringr",
+ "utils",
+ "uuid"
+ ],
+ "Hash": "6dd14cb88733b84d2b9af9fb8f64dbc5"
+ },
+ "timechange": {
+ "Package": "timechange",
+ "Version": "0.2.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cpp11"
+ ],
+ "Hash": "8548b44f79a35ba1791308b61e6012d7"
+ },
+ "tinytex": {
+ "Package": "tinytex",
+ "Version": "0.45",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "xfun"
+ ],
+ "Hash": "e4e357f28c2edff493936b6cb30c3d65"
+ },
+ "tzdb": {
+ "Package": "tzdb",
+ "Version": "0.4.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cpp11"
+ ],
+ "Hash": "f561504ec2897f4d46f0c7657e488ae1"
+ },
+ "units": {
+ "Package": "units",
+ "Version": "0.8-2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "Rcpp"
+ ],
+ "Hash": "422376fe53419adcde4710d43acbcdd0"
+ },
+ "utf8": {
+ "Package": "utf8",
+ "Version": "1.2.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "1fe17157424bb09c48a8b3b550c753bc"
+ },
+ "uuid": {
+ "Package": "uuid",
+ "Version": "1.1-0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "f1cb46c157d080b729159d407be83496"
+ },
+ "vctrs": {
+ "Package": "vctrs",
+ "Version": "0.6.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cli",
+ "glue",
+ "lifecycle",
+ "rlang"
+ ],
+ "Hash": "d0ef2856b83dc33ea6e255caf6229ee2"
+ },
+ "viridis": {
+ "Package": "viridis",
+ "Version": "0.6.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "ggplot2",
+ "gridExtra",
+ "viridisLite"
+ ],
+ "Hash": "80cd127bc8c9d3d9f0904ead9a9102f1"
+ },
+ "viridisLite": {
+ "Package": "viridisLite",
+ "Version": "0.4.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "c826c7c4241b6fc89ff55aaea3fa7491"
+ },
+ "vroom": {
+ "Package": "vroom",
+ "Version": "1.6.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "bit64",
+ "cli",
+ "cpp11",
+ "crayon",
+ "glue",
+ "hms",
+ "lifecycle",
+ "methods",
+ "progress",
+ "rlang",
+ "stats",
+ "tibble",
+ "tidyselect",
+ "tzdb",
+ "vctrs",
+ "withr"
+ ],
+ "Hash": "8318e64ffb3a70e652494017ec455561"
+ },
+ "waldo": {
+ "Package": "waldo",
+ "Version": "0.5.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "cli",
+ "diffobj",
+ "fansi",
+ "glue",
+ "methods",
+ "rematch2",
+ "rlang",
+ "tibble"
+ ],
+ "Hash": "2c993415154cdb94649d99ae138ff5e5"
+ },
+ "webdriver": {
+ "Package": "webdriver",
+ "Version": "1.0.6",
+ "Source": "Repository",
+ "Repository": "RSPM",
+ "Requirements": [
+ "R6",
+ "base64enc",
+ "callr",
+ "curl",
+ "debugme",
+ "httr",
+ "jsonlite",
+ "showimage",
+ "utils",
+ "withr"
+ ],
+ "Hash": "adc1e0db3ac0d75dcdb4b8179e7ca796"
+ },
+ "webutils": {
+ "Package": "webutils",
+ "Version": "1.1",
+ "Source": "Repository",
+ "Repository": "RSPM",
+ "Requirements": [
+ "curl",
+ "jsonlite"
+ ],
+ "Hash": "75d8b5b05fe22659b54076563f83f26a"
+ },
+ "whisker": {
+ "Package": "whisker",
+ "Version": "0.4.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "c6abfa47a46d281a7d5159d0a8891e88"
+ },
+ "withr": {
+ "Package": "withr",
+ "Version": "2.5.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "grDevices",
+ "graphics",
+ "stats"
+ ],
+ "Hash": "c0e49a9760983e81e55cdd9be92e7182"
+ },
+ "wk": {
+ "Package": "wk",
+ "Version": "0.7.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "68a7ab6ec1afb5f076172b983c069313"
+ },
+ "xfun": {
+ "Package": "xfun",
+ "Version": "0.39",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "stats",
+ "tools"
+ ],
+ "Hash": "8f56e9acb54fb525e66464d57ab58bcb"
+ },
+ "xml2": {
+ "Package": "xml2",
+ "Version": "1.3.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "methods"
+ ],
+ "Hash": "6c40e5cfcc6aefd88110666e18c31f40"
+ },
+ "xtable": {
+ "Package": "xtable",
+ "Version": "1.8-4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "stats",
+ "utils"
+ ],
+ "Hash": "b8acdf8af494d9ec19ccb2481a9b11c2"
+ },
+ "xts": {
+ "Package": "xts",
+ "Version": "0.13.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "methods",
+ "zoo"
+ ],
+ "Hash": "b8aa1235fd8b0ff10756150b792dc60f"
+ },
+ "yaml": {
+ "Package": "yaml",
+ "Version": "2.3.7",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "0d0056cc5383fbc240ccd0cb584bf436"
+ },
+ "zoo": {
+ "Package": "zoo",
+ "Version": "1.8-12",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "grDevices",
+ "graphics",
+ "lattice",
+ "stats",
+ "utils"
+ ],
+ "Hash": "5c715954112b45499fb1dadc6ee6ee3e"
+ }
+ }
+}
diff --git a/renv/.gitignore b/renv/.gitignore
new file mode 100644
index 0000000..0ec0cbb
--- /dev/null
+++ b/renv/.gitignore
@@ -0,0 +1,7 @@
+library/
+local/
+cellar/
+lock/
+python/
+sandbox/
+staging/
diff --git a/renv/activate.R b/renv/activate.R
new file mode 100644
index 0000000..cc742fc
--- /dev/null
+++ b/renv/activate.R
@@ -0,0 +1,1181 @@
+
+local({
+
+ # the requested version of renv
+ version <- "1.0.0"
+ attr(version, "sha") <- NULL
+
+ # the project directory
+ project <- getwd()
+
+ # figure out whether the autoloader is enabled
+ enabled <- local({
+
+ # first, check config option
+ override <- getOption("renv.config.autoloader.enabled")
+ if (!is.null(override))
+ return(override)
+
+ # next, check environment variables
+ # TODO: prefer using the configuration one in the future
+ envvars <- c(
+ "RENV_CONFIG_AUTOLOADER_ENABLED",
+ "RENV_AUTOLOADER_ENABLED",
+ "RENV_ACTIVATE_PROJECT"
+ )
+
+ for (envvar in envvars) {
+ envval <- Sys.getenv(envvar, unset = NA)
+ if (!is.na(envval))
+ return(tolower(envval) %in% c("true", "t", "1"))
+ }
+
+ # enable by default
+ TRUE
+
+ })
+
+ if (!enabled)
+ return(FALSE)
+
+ # avoid recursion
+ if (identical(getOption("renv.autoloader.running"), TRUE)) {
+ warning("ignoring recursive attempt to run renv autoloader")
+ return(invisible(TRUE))
+ }
+
+ # signal that we're loading renv during R startup
+ options(renv.autoloader.running = TRUE)
+ on.exit(options(renv.autoloader.running = NULL), add = TRUE)
+
+ # signal that we've consented to use renv
+ options(renv.consent = TRUE)
+
+ # load the 'utils' package eagerly -- this ensures that renv shims, which
+ # mask 'utils' packages, will come first on the search path
+ library(utils, lib.loc = .Library)
+
+ # unload renv if it's already been loaded
+ if ("renv" %in% loadedNamespaces())
+ unloadNamespace("renv")
+
+ # load bootstrap tools
+ `%||%` <- function(x, y) {
+ if (is.null(x)) y else x
+ }
+
+ catf <- function(fmt, ..., appendLF = TRUE) {
+
+ quiet <- getOption("renv.bootstrap.quiet", default = FALSE)
+ if (quiet)
+ return(invisible())
+
+ msg <- sprintf(fmt, ...)
+ cat(msg, file = stdout(), sep = if (appendLF) "\n" else "")
+
+ invisible(msg)
+
+ }
+
+ header <- function(label,
+ ...,
+ prefix = "#",
+ suffix = "-",
+ n = min(getOption("width"), 78))
+ {
+ label <- sprintf(label, ...)
+ n <- max(n - nchar(label) - nchar(prefix) - 2L, 8L)
+ if (n <= 0)
+ return(paste(prefix, label))
+
+ tail <- paste(rep.int(suffix, n), collapse = "")
+ paste0(prefix, " ", label, " ", tail)
+
+ }
+
+ startswith <- function(string, prefix) {
+ substring(string, 1, nchar(prefix)) == prefix
+ }
+
+ bootstrap <- function(version, library) {
+
+ friendly <- renv_bootstrap_version_friendly(version)
+ section <- header(sprintf("Bootstrapping renv %s", friendly))
+ catf(section)
+
+ # attempt to download renv
+ catf("- Downloading renv ... ", appendLF = FALSE)
+ withCallingHandlers(
+ tarball <- renv_bootstrap_download(version),
+ error = function(err) {
+ catf("FAILED")
+ stop("failed to download:\n", conditionMessage(err))
+ }
+ )
+ catf("OK")
+ on.exit(unlink(tarball), add = TRUE)
+
+ # now attempt to install
+ catf("- Installing renv ... ", appendLF = FALSE)
+ withCallingHandlers(
+ status <- renv_bootstrap_install(version, tarball, library),
+ error = function(err) {
+ catf("FAILED")
+ stop("failed to install:\n", conditionMessage(err))
+ }
+ )
+ catf("OK")
+
+ # add empty line to break up bootstrapping from normal output
+ catf("")
+
+ return(invisible())
+ }
+
+ renv_bootstrap_tests_running <- function() {
+ getOption("renv.tests.running", default = FALSE)
+ }
+
+ renv_bootstrap_repos <- function() {
+
+ # get CRAN repository
+ cran <- getOption("renv.repos.cran", "https://cloud.r-project.org")
+
+ # check for repos override
+ repos <- Sys.getenv("RENV_CONFIG_REPOS_OVERRIDE", unset = NA)
+ if (!is.na(repos)) {
+
+ # check for RSPM; if set, use a fallback repository for renv
+ rspm <- Sys.getenv("RSPM", unset = NA)
+ if (identical(rspm, repos))
+ repos <- c(RSPM = rspm, CRAN = cran)
+
+ return(repos)
+
+ }
+
+ # check for lockfile repositories
+ repos <- tryCatch(renv_bootstrap_repos_lockfile(), error = identity)
+ if (!inherits(repos, "error") && length(repos))
+ return(repos)
+
+ # retrieve current repos
+ repos <- getOption("repos")
+
+ # ensure @CRAN@ entries are resolved
+ repos[repos == "@CRAN@"] <- cran
+
+ # add in renv.bootstrap.repos if set
+ default <- c(FALLBACK = "https://cloud.r-project.org")
+ extra <- getOption("renv.bootstrap.repos", default = default)
+ repos <- c(repos, extra)
+
+ # remove duplicates that might've snuck in
+ dupes <- duplicated(repos) | duplicated(names(repos))
+ repos[!dupes]
+
+ }
+
+ renv_bootstrap_repos_lockfile <- function() {
+
+ lockpath <- Sys.getenv("RENV_PATHS_LOCKFILE", unset = "renv.lock")
+ if (!file.exists(lockpath))
+ return(NULL)
+
+ lockfile <- tryCatch(renv_json_read(lockpath), error = identity)
+ if (inherits(lockfile, "error")) {
+ warning(lockfile)
+ return(NULL)
+ }
+
+ repos <- lockfile$R$Repositories
+ if (length(repos) == 0)
+ return(NULL)
+
+ keys <- vapply(repos, `[[`, "Name", FUN.VALUE = character(1))
+ vals <- vapply(repos, `[[`, "URL", FUN.VALUE = character(1))
+ names(vals) <- keys
+
+ return(vals)
+
+ }
+
+ renv_bootstrap_download <- function(version) {
+
+ sha <- attr(version, "sha", exact = TRUE)
+
+ methods <- if (!is.null(sha)) {
+
+ # attempting to bootstrap a development version of renv
+ c(
+ function() renv_bootstrap_download_tarball(sha),
+ function() renv_bootstrap_download_github(sha)
+ )
+
+ } else {
+
+ # attempting to bootstrap a release version of renv
+ c(
+ function() renv_bootstrap_download_tarball(version),
+ function() renv_bootstrap_download_cran_latest(version),
+ function() renv_bootstrap_download_cran_archive(version)
+ )
+
+ }
+
+ for (method in methods) {
+ path <- tryCatch(method(), error = identity)
+ if (is.character(path) && file.exists(path))
+ return(path)
+ }
+
+ stop("All download methods failed")
+
+ }
+
+ renv_bootstrap_download_impl <- function(url, destfile) {
+
+ mode <- "wb"
+
+ # https://bugs.r-project.org/bugzilla/show_bug.cgi?id=17715
+ fixup <-
+ Sys.info()[["sysname"]] == "Windows" &&
+ substring(url, 1L, 5L) == "file:"
+
+ if (fixup)
+ mode <- "w+b"
+
+ args <- list(
+ url = url,
+ destfile = destfile,
+ mode = mode,
+ quiet = TRUE
+ )
+
+ if ("headers" %in% names(formals(utils::download.file)))
+ args$headers <- renv_bootstrap_download_custom_headers(url)
+
+ do.call(utils::download.file, args)
+
+ }
+
+ renv_bootstrap_download_custom_headers <- function(url) {
+
+ headers <- getOption("renv.download.headers")
+ if (is.null(headers))
+ return(character())
+
+ if (!is.function(headers))
+ stopf("'renv.download.headers' is not a function")
+
+ headers <- headers(url)
+ if (length(headers) == 0L)
+ return(character())
+
+ if (is.list(headers))
+ headers <- unlist(headers, recursive = FALSE, use.names = TRUE)
+
+ ok <-
+ is.character(headers) &&
+ is.character(names(headers)) &&
+ all(nzchar(names(headers)))
+
+ if (!ok)
+ stop("invocation of 'renv.download.headers' did not return a named character vector")
+
+ headers
+
+ }
+
+ renv_bootstrap_download_cran_latest <- function(version) {
+
+ spec <- renv_bootstrap_download_cran_latest_find(version)
+ type <- spec$type
+ repos <- spec$repos
+
+ baseurl <- utils::contrib.url(repos = repos, type = type)
+ ext <- if (identical(type, "source"))
+ ".tar.gz"
+ else if (Sys.info()[["sysname"]] == "Windows")
+ ".zip"
+ else
+ ".tgz"
+ name <- sprintf("renv_%s%s", version, ext)
+ url <- paste(baseurl, name, sep = "/")
+
+ destfile <- file.path(tempdir(), name)
+ status <- tryCatch(
+ renv_bootstrap_download_impl(url, destfile),
+ condition = identity
+ )
+
+ if (inherits(status, "condition"))
+ return(FALSE)
+
+ # report success and return
+ destfile
+
+ }
+
+ renv_bootstrap_download_cran_latest_find <- function(version) {
+
+ # check whether binaries are supported on this system
+ binary <-
+ getOption("renv.bootstrap.binary", default = TRUE) &&
+ !identical(.Platform$pkgType, "source") &&
+ !identical(getOption("pkgType"), "source") &&
+ Sys.info()[["sysname"]] %in% c("Darwin", "Windows")
+
+ types <- c(if (binary) "binary", "source")
+
+ # iterate over types + repositories
+ for (type in types) {
+ for (repos in renv_bootstrap_repos()) {
+
+ # retrieve package database
+ db <- tryCatch(
+ as.data.frame(
+ utils::available.packages(type = type, repos = repos),
+ stringsAsFactors = FALSE
+ ),
+ error = identity
+ )
+
+ if (inherits(db, "error"))
+ next
+
+ # check for compatible entry
+ entry <- db[db$Package %in% "renv" & db$Version %in% version, ]
+ if (nrow(entry) == 0)
+ next
+
+ # found it; return spec to caller
+ spec <- list(entry = entry, type = type, repos = repos)
+ return(spec)
+
+ }
+ }
+
+ # if we got here, we failed to find renv
+ fmt <- "renv %s is not available from your declared package repositories"
+ stop(sprintf(fmt, version))
+
+ }
+
+ renv_bootstrap_download_cran_archive <- function(version) {
+
+ name <- sprintf("renv_%s.tar.gz", version)
+ repos <- renv_bootstrap_repos()
+ urls <- file.path(repos, "src/contrib/Archive/renv", name)
+ destfile <- file.path(tempdir(), name)
+
+ for (url in urls) {
+
+ status <- tryCatch(
+ renv_bootstrap_download_impl(url, destfile),
+ condition = identity
+ )
+
+ if (identical(status, 0L))
+ return(destfile)
+
+ }
+
+ return(FALSE)
+
+ }
+
+ renv_bootstrap_download_tarball <- function(version) {
+
+ # if the user has provided the path to a tarball via
+ # an environment variable, then use it
+ tarball <- Sys.getenv("RENV_BOOTSTRAP_TARBALL", unset = NA)
+ if (is.na(tarball))
+ return()
+
+ # allow directories
+ if (dir.exists(tarball)) {
+ name <- sprintf("renv_%s.tar.gz", version)
+ tarball <- file.path(tarball, name)
+ }
+
+ # bail if it doesn't exist
+ if (!file.exists(tarball)) {
+
+ # let the user know we weren't able to honour their request
+ fmt <- "- RENV_BOOTSTRAP_TARBALL is set (%s) but does not exist."
+ msg <- sprintf(fmt, tarball)
+ warning(msg)
+
+ # bail
+ return()
+
+ }
+
+ catf("- Using local tarball '%s'.", tarball)
+ tarball
+
+ }
+
+ renv_bootstrap_download_github <- function(version) {
+
+ enabled <- Sys.getenv("RENV_BOOTSTRAP_FROM_GITHUB", unset = "TRUE")
+ if (!identical(enabled, "TRUE"))
+ return(FALSE)
+
+ # prepare download options
+ pat <- Sys.getenv("GITHUB_PAT")
+ if (nzchar(Sys.which("curl")) && nzchar(pat)) {
+ fmt <- "--location --fail --header \"Authorization: token %s\""
+ extra <- sprintf(fmt, pat)
+ saved <- options("download.file.method", "download.file.extra")
+ options(download.file.method = "curl", download.file.extra = extra)
+ on.exit(do.call(base::options, saved), add = TRUE)
+ } else if (nzchar(Sys.which("wget")) && nzchar(pat)) {
+ fmt <- "--header=\"Authorization: token %s\""
+ extra <- sprintf(fmt, pat)
+ saved <- options("download.file.method", "download.file.extra")
+ options(download.file.method = "wget", download.file.extra = extra)
+ on.exit(do.call(base::options, saved), add = TRUE)
+ }
+
+ url <- file.path("https://api.github.com/repos/rstudio/renv/tarball", version)
+ name <- sprintf("renv_%s.tar.gz", version)
+ destfile <- file.path(tempdir(), name)
+
+ status <- tryCatch(
+ renv_bootstrap_download_impl(url, destfile),
+ condition = identity
+ )
+
+ if (!identical(status, 0L))
+ return(FALSE)
+
+ renv_bootstrap_download_augment(destfile)
+
+ return(destfile)
+
+ }
+
+ # Add Sha to DESCRIPTION. This is stop gap until #890, after which we
+ # can use renv::install() to fully capture metadata.
+ renv_bootstrap_download_augment <- function(destfile) {
+ sha <- renv_bootstrap_git_extract_sha1_tar(destfile)
+ if (is.null(sha)) {
+ return()
+ }
+
+ # Untar
+ tempdir <- tempfile("renv-github-")
+ on.exit(unlink(tempdir, recursive = TRUE), add = TRUE)
+ untar(destfile, exdir = tempdir)
+ pkgdir <- dir(tempdir, full.names = TRUE)[[1]]
+
+ # Modify description
+ desc_path <- file.path(pkgdir, "DESCRIPTION")
+ desc_lines <- readLines(desc_path)
+ remotes_fields <- c(
+ "RemoteType: github",
+ "RemoteHost: api.github.com",
+ "RemoteRepo: renv",
+ "RemoteUsername: rstudio",
+ "RemotePkgRef: rstudio/renv",
+ paste("RemoteRef: ", sha),
+ paste("RemoteSha: ", sha)
+ )
+ writeLines(c(desc_lines[desc_lines != ""], remotes_fields), con = desc_path)
+
+ # Re-tar
+ local({
+ old <- setwd(tempdir)
+ on.exit(setwd(old), add = TRUE)
+
+ tar(destfile, compression = "gzip")
+ })
+ invisible()
+ }
+
+ # Extract the commit hash from a git archive. Git archives include the SHA1
+ # hash as the comment field of the tarball pax extended header
+ # (see https://www.kernel.org/pub/software/scm/git/docs/git-archive.html)
+ # For GitHub archives this should be the first header after the default one
+ # (512 byte) header.
+ renv_bootstrap_git_extract_sha1_tar <- function(bundle) {
+
+ # open the bundle for reading
+ # We use gzcon for everything because (from ?gzcon)
+ # > Reading from a connection which does not supply a ‘gzip’ magic
+ # > header is equivalent to reading from the original connection
+ conn <- gzcon(file(bundle, open = "rb", raw = TRUE))
+ on.exit(close(conn))
+
+ # The default pax header is 512 bytes long and the first pax extended header
+ # with the comment should be 51 bytes long
+ # `52 comment=` (11 chars) + 40 byte SHA1 hash
+ len <- 0x200 + 0x33
+ res <- rawToChar(readBin(conn, "raw", n = len)[0x201:len])
+
+ if (grepl("^52 comment=", res)) {
+ sub("52 comment=", "", res)
+ } else {
+ NULL
+ }
+ }
+
+ renv_bootstrap_install <- function(version, tarball, library) {
+
+ # attempt to install it into project library
+ dir.create(library, showWarnings = FALSE, recursive = TRUE)
+ output <- renv_bootstrap_install_impl(library, tarball)
+
+ # check for successful install
+ status <- attr(output, "status")
+ if (is.null(status) || identical(status, 0L))
+ return(status)
+
+ # an error occurred; report it
+ header <- "installation of renv failed"
+ lines <- paste(rep.int("=", nchar(header)), collapse = "")
+ text <- paste(c(header, lines, output), collapse = "\n")
+ stop(text)
+
+ }
+
+ renv_bootstrap_install_impl <- function(library, tarball) {
+
+ # invoke using system2 so we can capture and report output
+ bin <- R.home("bin")
+ exe <- if (Sys.info()[["sysname"]] == "Windows") "R.exe" else "R"
+ R <- file.path(bin, exe)
+
+ args <- c(
+ "--vanilla", "CMD", "INSTALL", "--no-multiarch",
+ "-l", shQuote(path.expand(library)),
+ shQuote(path.expand(tarball))
+ )
+
+ system2(R, args, stdout = TRUE, stderr = TRUE)
+
+ }
+
+ renv_bootstrap_platform_prefix <- function() {
+
+ # construct version prefix
+ version <- paste(R.version$major, R.version$minor, sep = ".")
+ prefix <- paste("R", numeric_version(version)[1, 1:2], sep = "-")
+
+ # include SVN revision for development versions of R
+ # (to avoid sharing platform-specific artefacts with released versions of R)
+ devel <-
+ identical(R.version[["status"]], "Under development (unstable)") ||
+ identical(R.version[["nickname"]], "Unsuffered Consequences")
+
+ if (devel)
+ prefix <- paste(prefix, R.version[["svn rev"]], sep = "-r")
+
+ # build list of path components
+ components <- c(prefix, R.version$platform)
+
+ # include prefix if provided by user
+ prefix <- renv_bootstrap_platform_prefix_impl()
+ if (!is.na(prefix) && nzchar(prefix))
+ components <- c(prefix, components)
+
+ # build prefix
+ paste(components, collapse = "/")
+
+ }
+
+ renv_bootstrap_platform_prefix_impl <- function() {
+
+ # if an explicit prefix has been supplied, use it
+ prefix <- Sys.getenv("RENV_PATHS_PREFIX", unset = NA)
+ if (!is.na(prefix))
+ return(prefix)
+
+ # if the user has requested an automatic prefix, generate it
+ auto <- Sys.getenv("RENV_PATHS_PREFIX_AUTO", unset = NA)
+ if (auto %in% c("TRUE", "True", "true", "1"))
+ return(renv_bootstrap_platform_prefix_auto())
+
+ # empty string on failure
+ ""
+
+ }
+
+ renv_bootstrap_platform_prefix_auto <- function() {
+
+ prefix <- tryCatch(renv_bootstrap_platform_os(), error = identity)
+ if (inherits(prefix, "error") || prefix %in% "unknown") {
+
+ msg <- paste(
+ "failed to infer current operating system",
+ "please file a bug report at https://github.com/rstudio/renv/issues",
+ sep = "; "
+ )
+
+ warning(msg)
+
+ }
+
+ prefix
+
+ }
+
+ renv_bootstrap_platform_os <- function() {
+
+ sysinfo <- Sys.info()
+ sysname <- sysinfo[["sysname"]]
+
+ # handle Windows + macOS up front
+ if (sysname == "Windows")
+ return("windows")
+ else if (sysname == "Darwin")
+ return("macos")
+
+ # check for os-release files
+ for (file in c("/etc/os-release", "/usr/lib/os-release"))
+ if (file.exists(file))
+ return(renv_bootstrap_platform_os_via_os_release(file, sysinfo))
+
+ # check for redhat-release files
+ if (file.exists("/etc/redhat-release"))
+ return(renv_bootstrap_platform_os_via_redhat_release())
+
+ "unknown"
+
+ }
+
+ renv_bootstrap_platform_os_via_os_release <- function(file, sysinfo) {
+
+ # read /etc/os-release
+ release <- utils::read.table(
+ file = file,
+ sep = "=",
+ quote = c("\"", "'"),
+ col.names = c("Key", "Value"),
+ comment.char = "#",
+ stringsAsFactors = FALSE
+ )
+
+ vars <- as.list(release$Value)
+ names(vars) <- release$Key
+
+ # get os name
+ os <- tolower(sysinfo[["sysname"]])
+
+ # read id
+ id <- "unknown"
+ for (field in c("ID", "ID_LIKE")) {
+ if (field %in% names(vars) && nzchar(vars[[field]])) {
+ id <- vars[[field]]
+ break
+ }
+ }
+
+ # read version
+ version <- "unknown"
+ for (field in c("UBUNTU_CODENAME", "VERSION_CODENAME", "VERSION_ID", "BUILD_ID")) {
+ if (field %in% names(vars) && nzchar(vars[[field]])) {
+ version <- vars[[field]]
+ break
+ }
+ }
+
+ # join together
+ paste(c(os, id, version), collapse = "-")
+
+ }
+
+ renv_bootstrap_platform_os_via_redhat_release <- function() {
+
+ # read /etc/redhat-release
+ contents <- readLines("/etc/redhat-release", warn = FALSE)
+
+ # infer id
+ id <- if (grepl("centos", contents, ignore.case = TRUE))
+ "centos"
+ else if (grepl("redhat", contents, ignore.case = TRUE))
+ "redhat"
+ else
+ "unknown"
+
+ # try to find a version component (very hacky)
+ version <- "unknown"
+
+ parts <- strsplit(contents, "[[:space:]]")[[1L]]
+ for (part in parts) {
+
+ nv <- tryCatch(numeric_version(part), error = identity)
+ if (inherits(nv, "error"))
+ next
+
+ version <- nv[1, 1]
+ break
+
+ }
+
+ paste(c("linux", id, version), collapse = "-")
+
+ }
+
+ renv_bootstrap_library_root_name <- function(project) {
+
+ # use project name as-is if requested
+ asis <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT_ASIS", unset = "FALSE")
+ if (asis)
+ return(basename(project))
+
+ # otherwise, disambiguate based on project's path
+ id <- substring(renv_bootstrap_hash_text(project), 1L, 8L)
+ paste(basename(project), id, sep = "-")
+
+ }
+
+ renv_bootstrap_library_root <- function(project) {
+
+ prefix <- renv_bootstrap_profile_prefix()
+
+ path <- Sys.getenv("RENV_PATHS_LIBRARY", unset = NA)
+ if (!is.na(path))
+ return(paste(c(path, prefix), collapse = "/"))
+
+ path <- renv_bootstrap_library_root_impl(project)
+ if (!is.null(path)) {
+ name <- renv_bootstrap_library_root_name(project)
+ return(paste(c(path, prefix, name), collapse = "/"))
+ }
+
+ renv_bootstrap_paths_renv("library", project = project)
+
+ }
+
+ renv_bootstrap_library_root_impl <- function(project) {
+
+ root <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT", unset = NA)
+ if (!is.na(root))
+ return(root)
+
+ type <- renv_bootstrap_project_type(project)
+ if (identical(type, "package")) {
+ userdir <- renv_bootstrap_user_dir()
+ return(file.path(userdir, "library"))
+ }
+
+ }
+
+ renv_bootstrap_validate_version <- function(version, description = NULL) {
+
+ # resolve description file
+ description <- description %||% {
+ path <- getNamespaceInfo("renv", "path")
+ packageDescription("renv", lib.loc = dirname(path))
+ }
+
+ # check whether requested version 'version' matches loaded version of renv
+ sha <- attr(version, "sha", exact = TRUE)
+ valid <- if (!is.null(sha))
+ renv_bootstrap_validate_version_dev(sha, description)
+ else
+ renv_bootstrap_validate_version_release(version, description)
+
+ if (valid)
+ return(TRUE)
+
+ # the loaded version of renv doesn't match the requested version;
+ # give the user instructions on how to proceed
+ remote <- if (!is.null(description[["RemoteSha"]])) {
+ paste("rstudio/renv", description[["RemoteSha"]], sep = "@")
+ } else {
+ paste("renv", description[["Version"]], sep = "@")
+ }
+
+ # display both loaded version + sha if available
+ friendly <- renv_bootstrap_version_friendly(
+ version = description[["Version"]],
+ sha = description[["RemoteSha"]]
+ )
+
+ fmt <- paste(
+ "renv %1$s was loaded from project library, but this project is configured to use renv %2$s.",
+ "- Use `renv::record(\"%3$s\")` to record renv %1$s in the lockfile.",
+ "- Use `renv::restore(packages = \"renv\")` to install renv %2$s into the project library.",
+ sep = "\n"
+ )
+ catf(fmt, friendly, renv_bootstrap_version_friendly(version), remote)
+
+ FALSE
+
+ }
+
+ renv_bootstrap_validate_version_dev <- function(version, description) {
+ expected <- description[["RemoteSha"]]
+ is.character(expected) && startswith(expected, version)
+ }
+
+ renv_bootstrap_validate_version_release <- function(version, description) {
+ expected <- description[["Version"]]
+ is.character(expected) && identical(expected, version)
+ }
+
+ renv_bootstrap_hash_text <- function(text) {
+
+ hashfile <- tempfile("renv-hash-")
+ on.exit(unlink(hashfile), add = TRUE)
+
+ writeLines(text, con = hashfile)
+ tools::md5sum(hashfile)
+
+ }
+
+ renv_bootstrap_load <- function(project, libpath, version) {
+
+ # try to load renv from the project library
+ if (!requireNamespace("renv", lib.loc = libpath, quietly = TRUE))
+ return(FALSE)
+
+ # warn if the version of renv loaded does not match
+ renv_bootstrap_validate_version(version)
+
+ # execute renv load hooks, if any
+ hooks <- getHook("renv::autoload")
+ for (hook in hooks)
+ if (is.function(hook))
+ tryCatch(hook(), error = warning)
+
+ # load the project
+ renv::load(project)
+
+ TRUE
+
+ }
+
+ renv_bootstrap_profile_load <- function(project) {
+
+ # if RENV_PROFILE is already set, just use that
+ profile <- Sys.getenv("RENV_PROFILE", unset = NA)
+ if (!is.na(profile) && nzchar(profile))
+ return(profile)
+
+ # check for a profile file (nothing to do if it doesn't exist)
+ path <- renv_bootstrap_paths_renv("profile", profile = FALSE, project = project)
+ if (!file.exists(path))
+ return(NULL)
+
+ # read the profile, and set it if it exists
+ contents <- readLines(path, warn = FALSE)
+ if (length(contents) == 0L)
+ return(NULL)
+
+ # set RENV_PROFILE
+ profile <- contents[[1L]]
+ if (!profile %in% c("", "default"))
+ Sys.setenv(RENV_PROFILE = profile)
+
+ profile
+
+ }
+
+ renv_bootstrap_profile_prefix <- function() {
+ profile <- renv_bootstrap_profile_get()
+ if (!is.null(profile))
+ return(file.path("profiles", profile, "renv"))
+ }
+
+ renv_bootstrap_profile_get <- function() {
+ profile <- Sys.getenv("RENV_PROFILE", unset = "")
+ renv_bootstrap_profile_normalize(profile)
+ }
+
+ renv_bootstrap_profile_set <- function(profile) {
+ profile <- renv_bootstrap_profile_normalize(profile)
+ if (is.null(profile))
+ Sys.unsetenv("RENV_PROFILE")
+ else
+ Sys.setenv(RENV_PROFILE = profile)
+ }
+
+ renv_bootstrap_profile_normalize <- function(profile) {
+
+ if (is.null(profile) || profile %in% c("", "default"))
+ return(NULL)
+
+ profile
+
+ }
+
+ renv_bootstrap_path_absolute <- function(path) {
+
+ substr(path, 1L, 1L) %in% c("~", "/", "\\") || (
+ substr(path, 1L, 1L) %in% c(letters, LETTERS) &&
+ substr(path, 2L, 3L) %in% c(":/", ":\\")
+ )
+
+ }
+
+ renv_bootstrap_paths_renv <- function(..., profile = TRUE, project = NULL) {
+ renv <- Sys.getenv("RENV_PATHS_RENV", unset = "renv")
+ root <- if (renv_bootstrap_path_absolute(renv)) NULL else project
+ prefix <- if (profile) renv_bootstrap_profile_prefix()
+ components <- c(root, renv, prefix, ...)
+ paste(components, collapse = "/")
+ }
+
+ renv_bootstrap_project_type <- function(path) {
+
+ descpath <- file.path(path, "DESCRIPTION")
+ if (!file.exists(descpath))
+ return("unknown")
+
+ desc <- tryCatch(
+ read.dcf(descpath, all = TRUE),
+ error = identity
+ )
+
+ if (inherits(desc, "error"))
+ return("unknown")
+
+ type <- desc$Type
+ if (!is.null(type))
+ return(tolower(type))
+
+ package <- desc$Package
+ if (!is.null(package))
+ return("package")
+
+ "unknown"
+
+ }
+
+ renv_bootstrap_user_dir <- function() {
+ dir <- renv_bootstrap_user_dir_impl()
+ path.expand(chartr("\\", "/", dir))
+ }
+
+ renv_bootstrap_user_dir_impl <- function() {
+
+ # use local override if set
+ override <- getOption("renv.userdir.override")
+ if (!is.null(override))
+ return(override)
+
+ # use R_user_dir if available
+ tools <- asNamespace("tools")
+ if (is.function(tools$R_user_dir))
+ return(tools$R_user_dir("renv", "cache"))
+
+ # try using our own backfill for older versions of R
+ envvars <- c("R_USER_CACHE_DIR", "XDG_CACHE_HOME")
+ for (envvar in envvars) {
+ root <- Sys.getenv(envvar, unset = NA)
+ if (!is.na(root))
+ return(file.path(root, "R/renv"))
+ }
+
+ # use platform-specific default fallbacks
+ if (Sys.info()[["sysname"]] == "Windows")
+ file.path(Sys.getenv("LOCALAPPDATA"), "R/cache/R/renv")
+ else if (Sys.info()[["sysname"]] == "Darwin")
+ "~/Library/Caches/org.R-project.R/R/renv"
+ else
+ "~/.cache/R/renv"
+
+ }
+
+ renv_bootstrap_version_friendly <- function(version, sha = NULL) {
+ sha <- sha %||% attr(version, "sha", exact = TRUE)
+ parts <- c(version, sprintf("[sha: %s]", substring(sha, 1L, 7L)))
+ paste(parts, collapse = " ")
+ }
+
+ renv_bootstrap_run <- function(version, libpath) {
+
+ # perform bootstrap
+ bootstrap(version, libpath)
+
+ # exit early if we're just testing bootstrap
+ if (!is.na(Sys.getenv("RENV_BOOTSTRAP_INSTALL_ONLY", unset = NA)))
+ return(TRUE)
+
+ # try again to load
+ if (requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) {
+ return(renv::load(project = getwd()))
+ }
+
+ # failed to download or load renv; warn the user
+ msg <- c(
+ "Failed to find an renv installation: the project will not be loaded.",
+ "Use `renv::activate()` to re-initialize the project."
+ )
+
+ warning(paste(msg, collapse = "\n"), call. = FALSE)
+
+ }
+
+
+ renv_bootstrap_in_rstudio <- function() {
+ commandArgs()[[1]] == "RStudio"
+ }
+
+ renv_json_read <- function(file = NULL, text = NULL) {
+
+ jlerr <- NULL
+
+ # if jsonlite is loaded, use that instead
+ if ("jsonlite" %in% loadedNamespaces()) {
+
+ json <- catch(renv_json_read_jsonlite(file, text))
+ if (!inherits(json, "error"))
+ return(json)
+
+ jlerr <- json
+
+ }
+
+ # otherwise, fall back to the default JSON reader
+ json <- catch(renv_json_read_default(file, text))
+ if (!inherits(json, "error"))
+ return(json)
+
+ # report an error
+ if (!is.null(jlerr))
+ stop(jlerr)
+ else
+ stop(json)
+
+ }
+
+ renv_json_read_jsonlite <- function(file = NULL, text = NULL) {
+ text <- paste(text %||% read(file), collapse = "\n")
+ jsonlite::fromJSON(txt = text, simplifyVector = FALSE)
+ }
+
+ renv_json_read_default <- function(file = NULL, text = NULL) {
+
+ # find strings in the JSON
+ text <- paste(text %||% read(file), collapse = "\n")
+ pattern <- '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
+ locs <- gregexpr(pattern, text, perl = TRUE)[[1]]
+
+ # if any are found, replace them with placeholders
+ replaced <- text
+ strings <- character()
+ replacements <- character()
+
+ if (!identical(c(locs), -1L)) {
+
+ # get the string values
+ starts <- locs
+ ends <- locs + attr(locs, "match.length") - 1L
+ strings <- substring(text, starts, ends)
+
+ # only keep those requiring escaping
+ strings <- grep("[[\\]{}:]", strings, perl = TRUE, value = TRUE)
+
+ # compute replacements
+ replacements <- sprintf('"\032%i\032"', seq_along(strings))
+
+ # replace the strings
+ mapply(function(string, replacement) {
+ replaced <<- sub(string, replacement, replaced, fixed = TRUE)
+ }, strings, replacements)
+
+ }
+
+ # transform the JSON into something the R parser understands
+ transformed <- replaced
+ transformed <- gsub("{}", "`names<-`(list(), character())", transformed, fixed = TRUE)
+ transformed <- gsub("[[{]", "list(", transformed, perl = TRUE)
+ transformed <- gsub("[]}]", ")", transformed, perl = TRUE)
+ transformed <- gsub(":", "=", transformed, fixed = TRUE)
+ text <- paste(transformed, collapse = "\n")
+
+ # parse it
+ json <- parse(text = text, keep.source = FALSE, srcfile = NULL)[[1L]]
+
+ # construct map between source strings, replaced strings
+ map <- as.character(parse(text = strings))
+ names(map) <- as.character(parse(text = replacements))
+
+ # convert to list
+ map <- as.list(map)
+
+ # remap strings in object
+ remapped <- renv_json_remap(json, map)
+
+ # evaluate
+ eval(remapped, envir = baseenv())
+
+ }
+
+ renv_json_remap <- function(json, map) {
+
+ # fix names
+ if (!is.null(names(json))) {
+ lhs <- match(names(json), names(map), nomatch = 0L)
+ rhs <- match(names(map), names(json), nomatch = 0L)
+ names(json)[rhs] <- map[lhs]
+ }
+
+ # fix values
+ if (is.character(json))
+ return(map[[json]] %||% json)
+
+ # handle true, false, null
+ if (is.name(json)) {
+ text <- as.character(json)
+ if (text == "true")
+ return(TRUE)
+ else if (text == "false")
+ return(FALSE)
+ else if (text == "null")
+ return(NULL)
+ }
+
+ # recurse
+ if (is.recursive(json)) {
+ for (i in seq_along(json)) {
+ json[i] <- list(renv_json_remap(json[[i]], map))
+ }
+ }
+
+ json
+
+ }
+
+ # load the renv profile, if any
+ renv_bootstrap_profile_load(project)
+
+ # construct path to library root
+ root <- renv_bootstrap_library_root(project)
+
+ # construct library prefix for platform
+ prefix <- renv_bootstrap_platform_prefix()
+
+ # construct full libpath
+ libpath <- file.path(root, prefix)
+
+ # attempt to load
+ if (renv_bootstrap_load(project, libpath, version))
+ return(TRUE)
+
+ if (renv_bootstrap_in_rstudio()) {
+ setHook("rstudio.sessionInit", function(...) {
+ renv_bootstrap_run(version, libpath)
+
+ # Work around buglet in RStudio if hook uses readline
+ tryCatch(
+ {
+ tools <- as.environment("tools:rstudio")
+ tools$.rs.api.sendToConsole("", echo = FALSE, focus = FALSE)
+ },
+ error = function(cnd) {}
+ )
+ })
+ } else {
+ renv_bootstrap_run(version, libpath)
+ }
+
+ invisible()
+
+})
diff --git a/renv/settings.json b/renv/settings.json
new file mode 100644
index 0000000..ffdbb32
--- /dev/null
+++ b/renv/settings.json
@@ -0,0 +1,19 @@
+{
+ "bioconductor.version": null,
+ "external.libraries": [],
+ "ignored.packages": [],
+ "package.dependency.fields": [
+ "Imports",
+ "Depends",
+ "LinkingTo"
+ ],
+ "ppm.enabled": null,
+ "ppm.ignored.urls": [],
+ "r.version": null,
+ "snapshot.type": "implicit",
+ "use.cache": true,
+ "vcs.ignore.cellar": true,
+ "vcs.ignore.library": true,
+ "vcs.ignore.local": true,
+ "vcs.manage.ignores": true
+}