#' Scenario to reach a fixed target
#'
#' @description
#' Those scenarios allow to reach a target value from a baseline year by target
#' year.
#'
#' `scenario_fixed_target()` provides values for scenarios stated as "Reach XX% in INDICATOR by
#' YEAR" or "Eliminate XX by YEAR".
#'
#' `scenario_fixed_target_col()` wraps around `scenario_fixed_target` to provide
#' targets from a column specified in `target_col` rather than a single value.
#'
#' `scenario_halt_rise()` is a special case of `scenario_fixed_target_col()`
#' where each country aims at a value of a specific year.
#'
#' The returned scenario is a portion of the straight line drawn from the
#' `baseline_year` value to the `target_year`. Only values for years between
#' `start_year` and `end_year` will be returned.
#'
#' If `value_col` has values that are higher or lower than the scenario values, then
#' only `value_col` will be kept, depending on `small_is_best`. For instance,
#' if the scenario value is 80 and the value 75 and small_is_best is TRUE, then
#' 75 will be kept.
#'
#' @inheritParams scenario_percent_baseline
#' @param target_value value to be achieved by scenario by `target_year`
#' @param small_is_best Logical to identify if a lower value is better than a higher
#' one (e.g. lower obesity in a positive public health outcome, so obesity rate
#' should have small_is_best = TRUE).
#' @param default_scenario name of the default scenario to be used.
#' @inheritParams trim_values
#'
#' @family fixed_target
#'
#' @rdname fixed_target
#'
scenario_fixed_target <- function(df,
target_value,
value_col = "value",
scenario_col = "scenario",
start_year = 2018,
end_year = 2025,
baseline_year = start_year,
target_year = end_year,
scenario_name = glue::glue("{target_value}_{target_year}"),
small_is_best = FALSE,
trim = TRUE,
keep_better_values = TRUE,
upper_limit = 100,
lower_limit = 0,
trim_years = TRUE,
start_year_trim = start_year,
end_year_trim = end_year,
ind_ids = billion_ind_codes("all"),
default_scenario = "default") {
assert_columns(df, "year", "iso3", "ind", value_col, scenario_col)
assert_unique_rows(df, scenario_col, ind_ids = ind_ids)
full_years_df <- tidyr::expand_grid(
"year" := start_year:end_year,
"iso3" := unique(df[["iso3"]]),
"ind" := unique(df[["ind"]]),
"{scenario_col}" := default_scenario
)
target_value <- as.numeric(target_value)
target_year <- as.numeric(target_year)
scenario_df <- df %>%
dplyr::full_join(full_years_df, by = c("year", "iso3", "ind", scenario_col)) %>%
dplyr::filter(.data[[scenario_col]] == default_scenario) %>%
dplyr::group_by(.data[["ind"]], .data[["iso3"]]) %>%
dplyr::mutate(
"baseline_year_" := get_baseline_year(.data[["year"]], .data[["type"]], baseline_year = !!baseline_year, type_filter = c("reported", "estimated", "imputed", "projected")),
"baseline_value_" := get_baseline_value(.data[[value_col]],
.data[["year"]],
.data[["type"]],
baseline_year = .data[["baseline_year_"]],
type_filter = c("all"))) %>%
dplyr::ungroup() %>%
dplyr::mutate(
"baseline_value_" := dplyr::case_when(
is.na(.data[["baseline_value_"]]) ~ as.numeric(0),
TRUE ~ as.numeric(.data[["baseline_value_"]])
),
scenario_value = calculate_fixed_target(target_value, small_is_best, .data[["year"]], baseline_year, target_year, .data[["baseline_value_"]], .data[["value"]]),
!!sym(scenario_col) := scenario_name
) %>%
dplyr::select(-c("baseline_value_", "baseline_year_")) %>%
trim_values(
col = "scenario_value",
value_col = value_col,
trim = trim,
small_is_best = small_is_best,
keep_better_values = keep_better_values,
upper_limit = upper_limit,
lower_limit = lower_limit,
trim_years = trim_years,
start_year_trim = start_year_trim,
end_year_trim = end_year_trim
) %>%
dplyr::mutate(type = dplyr::case_when(
!is.na(.data[["type"]]) ~ .data[["type"]],
TRUE ~ "projected"
))
df %>%
dplyr::bind_rows(scenario_df)
}
#' Calculate fixed target from a baseline year by a target year
#'
#' The returned values are a portion of the straight line drawn from the
#' `baseline_year` value to the `target_year`. Only values for years between
#' `start_year` and `end_year` will be returned.
#'
#' @param target_value vector of values to use as targets
#' @param baseline_value value at baseline_year
#' @param year (vector) vector of years
#' @param original_value (vector) vector of the original values. returned for years before the baseline year
#'
#' @noRd
calculate_fixed_target <- function(target_value,
small_is_best,
year,
baseline_year,
target_year,
baseline_value,
original_value) {
if (small_is_best) {
dplyr::case_when(
year >= baseline_year & year <= target_year ~
baseline_value + (target_value - baseline_value) * (year - baseline_year) / (target_year - baseline_year),
year > target_year ~ target_value,
year < baseline_year ~ original_value,
TRUE ~ NA_real_
)
} else {
dplyr::case_when(
year >= baseline_year & year <= target_year ~
baseline_value + (target_value - baseline_value) * (year - baseline_year) / (target_year - baseline_year),
year > target_year ~ target_value,
year < baseline_year ~ original_value,
TRUE ~ NA_real_
)
}
}
#' @param target_col name of column with targets
#'
#' @rdname fixed_target
scenario_fixed_target_col <- function(df,
value_col = "value",
scenario_col = "scenario",
start_year = 2018,
end_year = 2025,
baseline_year = start_year,
target_col = "target",
target_year = end_year,
scenario_name = glue::glue("{target_col}_{target_year}"),
small_is_best = FALSE,
trim = TRUE,
keep_better_values = TRUE,
upper_limit = 100,
lower_limit = 0,
trim_years = TRUE,
start_year_trim = start_year,
end_year_trim = end_year,
ind_ids = billion_ind_codes("all"),
default_scenario = "default") {
full_years_df <- tidyr::expand_grid(
"year" := start_year:end_year,
"iso3" := unique(df[["iso3"]]),
"ind" := unique(df[["ind"]]),
"{scenario_col}" := default_scenario
)
target_df <- df %>%
dplyr::select(dplyr::all_of(c("iso3", "ind", target_col))) %>%
dplyr::distinct()
scenario_df <- df %>%
dplyr::full_join(full_years_df, by = c("year", "iso3", "ind", scenario_col)) %>%
dplyr::select(-tidyselect::all_of(target_col)) %>%
dplyr::left_join(target_df, by = c("iso3", "ind")) %>%
dplyr::filter(.data[[scenario_col]] == default_scenario)
scenario_df <- scenario_fixed_target(
df = scenario_df,
target_value = scenario_df[[target_col]],
value_col = value_col,
start_year = start_year,
end_year = end_year,
baseline_year = baseline_year,
target_year = target_year,
scenario_name = scenario_name,
small_is_best = small_is_best,
trim = trim,
keep_better_values = keep_better_values,
upper_limit = upper_limit,
lower_limit = lower_limit,
trim_years = trim_years,
start_year_trim = start_year_trim,
end_year_trim = end_year_trim,
ind_ids = ind_ids,
default_scenario = default_scenario
) %>%
dplyr::filter(!is.na(.data[[value_col]])) %>%
dplyr::distinct()
df %>%
dplyr::bind_rows(scenario_df)
}
#' @rdname fixed_target
scenario_halt_rise <- function(df,
value_col = "value",
start_year = 2018,
end_year = 2025,
baseline_year = start_year,
target_year = end_year,
scenario_col = "scenario",
scenario_name = glue::glue("halt_rise"),
upper_limit = 100,
lower_limit = 0,
trim = TRUE,
keep_better_values = FALSE,
small_is_best = FALSE,
trim_years = TRUE,
start_year_trim = start_year,
end_year_trim = end_year,
ind_ids = billion_ind_codes("all"),
default_scenario = "default") {
assert_columns(df, "year", "iso3", "ind", value_col, scenario_col)
assert_unique_rows(df, scenario_col, ind_ids = ind_ids)
target_df <- df %>%
dplyr::group_by(.data[["iso3"]], .data[["ind"]]) %>%
dplyr::mutate("target" := get_baseline_value(.data[[value_col]],
.data[["year"]],
.data[["type"]],
.data[[scenario_col]],
default_scenario,
baseline_year,
type_filter = c("all"))) %>%
dplyr::ungroup()
scenario_fixed_target_col(target_df,
value_col = value_col,
scenario_col = scenario_col,
start_year = start_year,
end_year = end_year,
baseline_year = start_year,
target_col = "target",
target_year = target_year,
scenario_name = scenario_name,
small_is_best = small_is_best,
trim = trim,
keep_better_values = keep_better_values,
upper_limit = upper_limit,
lower_limit = lower_limit,
trim_years = trim_years,
start_year_trim = start_year_trim,
end_year_trim = end_year_trim,
ind_ids = ind_ids,
default_scenario = default_scenario) %>%
dplyr::select(-"target")
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.