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 +}