From 4d644d6dfb6dd4a333a9464420a76c34c04ee406 Mon Sep 17 00:00:00 2001 From: Kalash Singhal <125359076+kalashsinghal@users.noreply.github.com> Date: Mon, 28 Oct 2024 00:49:17 +0530 Subject: [PATCH] Add `tiltTransitionRisk` code (#24) * Refactor * refactor * refactor * refactor * refactor * refactor --- DESCRIPTION | 18 +- NAMESPACE | 64 +- R/add_thresholds_transition_risk.R | 8 +- R/add_transition_risk_NA_share.R | 98 +++ ...ransition_risk_category_at_company_level.R | 53 ++ ...ansition_risk_category_at_product_level.R} | 4 +- R/best_case_worst_case_avg_profile_ranking.R | 56 ++ ...st_case_worst_case_avg_reduction_targets.R | 59 ++ ..._case_worst_case_transition_risk_profile.R | 30 + ...transition_risk_profile_at_company_level.R | 65 ++ ...ent_of_variation_transition_risk_profile.R | 133 ++++ R/col-transition_risk_profile.R | 8 - R/cols-best_case_worst_case.R | 35 + R/example_data.R | 140 ++++ R/exclude_cols_then_pivot_wider.R | 91 +++ R/pivot_wider_transition_risk_profile.R | 204 +++++ R/prepare_webtool_output.R | 43 + R/relocate_transition_risk_profile_cols.R | 108 +++ R/round_off_to_4_decimal_places.R | 16 + R/score_transition_risk.R | 124 +++ R/score_transition_risk_and_polish.R | 222 ++++++ R/tiltTransitionRisk-options.R | 62 ++ R/tiltTransitionRisk-package.R | 54 ++ R/transition_risk_profile.R | 185 +++++ R/utils-score_transition_risk.R | 127 +++ R/utils.R | 12 + man/add_benchmark_tr_score.Rd | 4 +- ...nsition_risk_category_at_product_level.Rd} | 10 +- man/add_transition_risk_score.Rd | 4 +- ...case_worst_case_transition_risk_profile.Rd | 18 + ...mple_emissions_profile_at_product_level.Rd | 22 + man/exclude_cols_then_pivot_wider.Rd | 85 ++ man/pivot_wider_transition_risk_profile.Rd | 77 ++ man/score_transition_risk.Rd | 73 ++ man/score_transition_risk_and_polish.Rd | 82 ++ man/tiltIndicatorAfter_options.Rd | 59 ++ man/tiltTransitionRisk-package.Rd | 14 +- man/transition_risk_profile.Rd | 99 +++ .../_snaps/exclude_cols_then_pivot_wider.md | 4 + ...ansition_risk_category_at_product_level.R} | 8 +- ...avg_profile_ranking_best_case_worst_case.R | 94 +++ ...avg_transition_risk_best_case_worst_case.R | 97 +++ ...st_case_worst_case_avg_reduction_targets.R | 107 +++ ..._case_worst_case_transition_risk_profile.R | 138 ++++ .../testthat/test-coefficient_of_variation.R | 107 +++ ...-create_risk_categories_at_company_level.R | 31 + .../test-exclude_cols_then_pivot_wider.R | 60 ++ tests/testthat/test-score_transition_risk.R | 239 ++++++ .../test-score_transition_risk_and_polish.R | 112 +++ tests/testthat/test-transition_risk_profile.R | 746 ++++++++++++++++++ 50 files changed, 4274 insertions(+), 35 deletions(-) create mode 100644 R/add_transition_risk_NA_share.R create mode 100644 R/add_transition_risk_category_at_company_level.R rename R/{add_transition_risk_category.R => add_transition_risk_category_at_product_level.R} (87%) create mode 100644 R/best_case_worst_case_avg_profile_ranking.R create mode 100644 R/best_case_worst_case_avg_reduction_targets.R create mode 100644 R/best_case_worst_case_transition_risk_profile.R create mode 100644 R/best_case_worst_case_transition_risk_profile_at_company_level.R create mode 100644 R/coefficient_of_variation_transition_risk_profile.R create mode 100644 R/cols-best_case_worst_case.R create mode 100644 R/example_data.R create mode 100644 R/exclude_cols_then_pivot_wider.R create mode 100644 R/pivot_wider_transition_risk_profile.R create mode 100644 R/prepare_webtool_output.R create mode 100644 R/relocate_transition_risk_profile_cols.R create mode 100644 R/round_off_to_4_decimal_places.R create mode 100644 R/score_transition_risk.R create mode 100644 R/score_transition_risk_and_polish.R create mode 100644 R/tiltTransitionRisk-options.R create mode 100644 R/transition_risk_profile.R create mode 100644 R/utils-score_transition_risk.R create mode 100644 R/utils.R rename man/{add_transition_risk_category.Rd => add_transition_risk_category_at_product_level.Rd} (68%) create mode 100644 man/best_case_worst_case_transition_risk_profile.Rd create mode 100644 man/example_emissions_profile_at_product_level.Rd create mode 100644 man/exclude_cols_then_pivot_wider.Rd create mode 100644 man/pivot_wider_transition_risk_profile.Rd create mode 100644 man/score_transition_risk.Rd create mode 100644 man/score_transition_risk_and_polish.Rd create mode 100644 man/tiltIndicatorAfter_options.Rd create mode 100644 man/transition_risk_profile.Rd create mode 100644 tests/testthat/_snaps/exclude_cols_then_pivot_wider.md rename tests/testthat/{test-add_transition_risk_category.R => test-add_transition_risk_category_at_product_level.R} (82%) create mode 100644 tests/testthat/test-avg_profile_ranking_best_case_worst_case.R create mode 100644 tests/testthat/test-avg_transition_risk_best_case_worst_case.R create mode 100644 tests/testthat/test-best_case_worst_case_avg_reduction_targets.R create mode 100644 tests/testthat/test-best_case_worst_case_transition_risk_profile.R create mode 100644 tests/testthat/test-coefficient_of_variation.R create mode 100644 tests/testthat/test-create_risk_categories_at_company_level.R create mode 100644 tests/testthat/test-exclude_cols_then_pivot_wider.R create mode 100644 tests/testthat/test-score_transition_risk.R create mode 100644 tests/testthat/test-score_transition_risk_and_polish.R create mode 100644 tests/testthat/test-transition_risk_profile.R diff --git a/DESCRIPTION b/DESCRIPTION index f264ab6..a702f7b 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -24,16 +24,22 @@ Imports: rlang, stats, tibble, + tidyr, + tidyselect, tiltIndicator (>= 0.0.0.9223), + tiltIndicatorAfter (>= 0.0.0.9061), + tiltPolish (>= 0.0.0.9006), tiltToyData (>= 0.0.0.9204), - utils -Suggests: - testthat (>= 3.0.0), + utils, withr -Remotes: +Suggests: + testthat (>= 3.0.0) +Remotes: 2DegreesInvesting/tiltIndicator, - 2degreesinvesting/tiltToyData + 2degreesinvesting/tiltToyData, + 2degreesinvesting/tiltIndicatorAfter, + 2degreesinvesting/tiltPolish Config/testthat/edition: 3 Encoding: UTF-8 Roxygen: list(markdown = TRUE) -RoxygenNote: 7.3.1 +RoxygenNote: 7.3.2 diff --git a/NAMESPACE b/NAMESPACE index 8a7097c..f6f7e5d 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -2,26 +2,88 @@ export(add_benchmark_tr_score) export(add_thresholds_transition_risk) -export(add_transition_risk_category) +export(add_transition_risk_category_at_product_level) export(add_transition_risk_score) +export(best_case_worst_case_transition_risk_profile) +export(example_emissions_profile_at_product_level) +export(example_sector_profile_at_product_level) +export(exclude_cols_then_pivot_wider) +export(pivot_wider_transition_risk_profile) +export(score_transition_risk) +export(score_transition_risk_and_polish) export(toy_all_activities_scenario_sectors) +export(transition_risk_profile) importFrom(dplyr,.data) +importFrom(dplyr,across) importFrom(dplyr,all_of) +importFrom(dplyr,arrange) +importFrom(dplyr,bind_rows) +importFrom(dplyr,case_when) +importFrom(dplyr,coalesce) importFrom(dplyr,distinct) importFrom(dplyr,filter) importFrom(dplyr,full_join) +importFrom(dplyr,left_join) importFrom(dplyr,mutate) +importFrom(dplyr,n_distinct) +importFrom(dplyr,relocate) +importFrom(dplyr,rename) +importFrom(dplyr,rename_with) importFrom(dplyr,select) +importFrom(dplyr,summarise) +importFrom(dplyr,where) importFrom(glue,glue) importFrom(purrr,walk) importFrom(readr,read_csv) +importFrom(rlang,":=") +importFrom(rlang,.data) importFrom(rlang,abort) +importFrom(rlang,as_name) +importFrom(rlang,ensym) importFrom(stats,quantile) +importFrom(tibble,tibble) importFrom(tibble,tribble) +importFrom(tidyr,pivot_wider) +importFrom(tidyselect,all_of) +importFrom(tidyselect,any_of) +importFrom(tidyselect,matches) importFrom(tiltIndicator,categorize_risk) +importFrom(tiltIndicator,epa_at_company_level) importFrom(tiltIndicator,epa_compute_profile_ranking) +importFrom(tiltIndicator,example_data_factory) +importFrom(tiltIndicator,insert_row_with_na_in_risk_category) +importFrom(tiltIndicator,nest_levels) importFrom(tiltIndicator,spa_compute_profile_ranking) +importFrom(tiltIndicator,tilt_profile) +importFrom(tiltIndicator,unnest_company) +importFrom(tiltIndicator,unnest_product) +importFrom(tiltIndicatorAfter,best_case_worst_case_emission_profile) +importFrom(tiltIndicatorAfter,best_case_worst_case_impl) +importFrom(tiltIndicatorAfter,best_case_worst_case_sector_profile) +importFrom(tiltIndicatorAfter,polish_best_case_worst_case) +importFrom(tiltIndicatorAfter,profile_emissions) +importFrom(tiltIndicatorAfter,profile_sector) +importFrom(tiltIndicatorAfter,rename_with_prefix) +importFrom(tiltPolish,rename_transition_risk_profile_cols_company) +importFrom(tiltPolish,rename_transition_risk_profile_cols_product) +importFrom(tiltPolish,rename_webtool_cols_at_company_level_wide) +importFrom(tiltPolish,select_webtool_cols_at_company_level_wide) +importFrom(tiltPolish,select_webtool_cols_at_product_level) +importFrom(tiltToyData,toy_ecoinvent_activities) +importFrom(tiltToyData,toy_ecoinvent_europages) +importFrom(tiltToyData,toy_ecoinvent_inputs) +importFrom(tiltToyData,toy_emissions_profile_any_companies) +importFrom(tiltToyData,toy_emissions_profile_products) importFrom(tiltToyData,toy_emissions_profile_products_ecoinvent) +importFrom(tiltToyData,toy_emissions_profile_upstream_products) +importFrom(tiltToyData,toy_emissions_profile_upstream_products_ecoinvent) +importFrom(tiltToyData,toy_europages_companies) +importFrom(tiltToyData,toy_isic_name) importFrom(tiltToyData,toy_sector_profile_any_scenarios) importFrom(tiltToyData,toy_sector_profile_companies) +importFrom(tiltToyData,toy_sector_profile_upstream_companies) +importFrom(tiltToyData,toy_sector_profile_upstream_products) +importFrom(utils,hasName) importFrom(utils,write.csv) +importFrom(withr,local_options) +importFrom(withr,local_seed) diff --git a/R/add_thresholds_transition_risk.R b/R/add_thresholds_transition_risk.R index b6a03f5..8bd221c 100644 --- a/R/add_thresholds_transition_risk.R +++ b/R/add_thresholds_transition_risk.R @@ -63,8 +63,8 @@ add_thresholds_transition_risk <- function(co2, #' Calulate `transition_risk_score` column #' #' @param data Dataframe. -#' @param profile_ranking Dataframe column. -#' @param reduction_targets Dataframe column. +#' @param col_ranking Dataframe column. +#' @param col_target Dataframe column. #' @keywords internal #' @export add_transition_risk_score <- function(data, @@ -83,8 +83,8 @@ add_transition_risk_score <- function(data, #' Calulate `benchmark_tr_score` column #' #' @param data Dataframe. -#' @param profile_ranking Dataframe column. -#' @param reduction_targets Dataframe column. +#' @param col_ranking Dataframe column. +#' @param col_target Dataframe column. #' @keywords internal #' @export add_benchmark_tr_score <- function(data, diff --git a/R/add_transition_risk_NA_share.R b/R/add_transition_risk_NA_share.R new file mode 100644 index 0000000..27a82cc --- /dev/null +++ b/R/add_transition_risk_NA_share.R @@ -0,0 +1,98 @@ +add_transition_risk_NA_share <- function(data) { + product <- data |> + unnest_product() |> + add_transition_risk_NA_share_at_product_level() + + company <- data |> + unnest_company() |> + select_and_join_transition_risk_NA_share_at_company_level(product) + + tilt_profile(nest_levels(product, company)) +} + +add_transition_risk_NA_share_at_product_level <- function(data) { + data |> + fill_benchmark_tr_score() |> + transition_risk_NA_amount_all() |> + transition_risk_NA_amount_benchmarks() |> + transition_risk_NA_total() |> + transition_risk_NA_share() |> + polish_transition_risk_NA_share() +} + +select_and_join_transition_risk_NA_share_at_company_level <- function(data, product) { + join_table <- product |> + select(all_of(c( + "companies_id", + "benchmark_tr_score", + "transition_risk_NA_share" + ))) |> + distinct() + + data |> + left_join( + join_table, + by = c("companies_id", + "benchmark_tr_score_avg" = "benchmark_tr_score" + ) + ) +} + +fill_benchmark_tr_score <- function(data) { + mutate(data, benchmark_tr_score = ifelse( + is.na(.data[[col_transition_risk_grouped_by()]]), + paste(.data[[col_scenario()]], + .data[[col_year()]], + .data[[col_emission_grouped_by()]], + sep = "_" + ), + .data[[col_transition_risk_grouped_by()]] + )) +} + +transition_risk_NA_amount_all <- function(data) { + mutate(data, + transition_risk_NA_amount_all = n_distinct( + .data[[col_europages_product()]][is.na(.data$matched_activity_name) | is.na(.data$reduction_targets)] + ), + .by = col_companies_id() + ) +} + +transition_risk_NA_amount_benchmarks <- function(data) { + mutate(data, + transition_risk_NA_amount_benchmarks = n_distinct( + .data[[col_europages_product()]][is.na(.data$transition_risk_score)] + ), + .by = all_of(c(col_companies_id(), col_transition_risk_grouped_by())) + ) +} + +transition_risk_NA_total <- function(data) { + mutate(data, + transition_risk_NA_total = ifelse( + is.na(.data$matched_activity_name) | is.na(.data$reduction_targets), + .data$transition_risk_NA_amount_all, + .data$transition_risk_NA_amount_all + .data$transition_risk_NA_amount_benchmarks + ), + .by = all_of(c(col_companies_id(), col_transition_risk_grouped_by())) + ) +} + +transition_risk_NA_share <- function(data) { + mutate(data, + transition_risk_NA_share = ifelse( + .data$amount_of_distinct_products == 0, + NA, + .data$transition_risk_NA_total / .data$amount_of_distinct_products + ), + .by = all_of(c(col_companies_id(), col_transition_risk_grouped_by())) + ) +} + +polish_transition_risk_NA_share <- function(data) { + select(data, -all_of(c( + "transition_risk_NA_amount_all", + "transition_risk_NA_amount_benchmarks" + ))) +} diff --git a/R/add_transition_risk_category_at_company_level.R b/R/add_transition_risk_category_at_company_level.R new file mode 100644 index 0000000..ca1a47e --- /dev/null +++ b/R/add_transition_risk_category_at_company_level.R @@ -0,0 +1,53 @@ +add_transition_risk_category_at_company_level <- function(data) { + product <- data |> + unnest_product() + + risk_categories <- product |> + create_risk_categories_at_company_level() + + company <- data |> + unnest_company() |> + join_risk_categories_at_company_level(risk_categories) + + tilt_profile(nest_levels(product, company)) +} + +create_risk_categories_at_company_level <- function(data) { + data |> + adapt_tr_product_cols_to_tiltIndicator_cols() |> + epa_at_company_level() |> + insert_row_with_na_in_risk_category() |> + adapt_tiltIndicator_cols_to_tr_company_cols() +} + +join_risk_categories_at_company_level <- function(data, risk_categories) { + data |> + create_transition_risk_category_col_at_company_level() |> + left_join(risk_categories, by = c( + "companies_id", + "benchmark_tr_score_avg", + "transition_risk_category" + )) +} + +adapt_tr_product_cols_to_tiltIndicator_cols <- function(data) { + rename(data, + grouped_by = "benchmark_tr_score", + risk_category = "transition_risk_category" + ) +} + +adapt_tiltIndicator_cols_to_tr_company_cols <- function(data) { + rename(data, + benchmark_tr_score_avg = "grouped_by", + transition_risk_category = "risk_category", + transition_risk_category_share = "value" + ) +} + +create_transition_risk_category_col_at_company_level <- function(data) { + mutate(data, transition_risk_category = coalesce( + .data$emission_profile, + .data$sector_profile + )) +} diff --git a/R/add_transition_risk_category.R b/R/add_transition_risk_category_at_product_level.R similarity index 87% rename from R/add_transition_risk_category.R rename to R/add_transition_risk_category_at_product_level.R index 9e35d21..4e43bf5 100644 --- a/R/add_transition_risk_category.R +++ b/R/add_transition_risk_category_at_product_level.R @@ -23,9 +23,9 @@ #' scenarios #' ) #' -#' output <- add_transition_risk_category(transition_risk_thresholds) +#' output <- add_transition_risk_category_at_product_level(transition_risk_thresholds) #' output -add_transition_risk_category <- function(data) { +add_transition_risk_category_at_product_level <- function(data) { check_crucial_cols(data, c( col_transition_risk_score(), col_tr_low_threshold(), col_tr_high_threshold() diff --git a/R/best_case_worst_case_avg_profile_ranking.R b/R/best_case_worst_case_avg_profile_ranking.R new file mode 100644 index 0000000..2d1899f --- /dev/null +++ b/R/best_case_worst_case_avg_profile_ranking.R @@ -0,0 +1,56 @@ +best_case_worst_case_avg_profile_ranking <- function(data) { + product <- data |> + unnest_product() + + avg_best_case_worst_case_at_product_level <- product |> + prepare_for_join_at_company_level_profile_ranking() + + avg_best_case <- prepare_avg_best_case_join_table_profile_ranking( + avg_best_case_worst_case_at_product_level + ) + avg_worst_case <- prepare_avg_worst_case_join_table_profile_ranking( + avg_best_case_worst_case_at_product_level + ) + + company <- data |> + unnest_company() |> + left_join(avg_best_case, by = c( + col_companies_id(), + col_emission_grouped_by() + )) |> + left_join(avg_worst_case, by = c( + col_companies_id(), + col_emission_grouped_by() + )) + + tilt_profile(nest_levels(product, company)) +} + +prepare_for_join_at_company_level_profile_ranking <- function(data) { + data |> + select(all_of(c( + col_companies_id(), + col_emission_grouped_by(), + "emissions_profile_best_case", + "emissions_profile_worst_case" + ))) |> + distinct() |> + rename("avg_profile_ranking_best_case" = "emissions_profile_best_case", + "avg_profile_ranking_worst_case" = "emissions_profile_worst_case") +} + +prepare_avg_worst_case_join_table_profile_ranking <- function(data) { + data |> + prepare_avg_best_case_join_table( + "avg_profile_ranking_best_case", + "avg_profile_ranking_worst_case" + ) +} + +prepare_avg_best_case_join_table_profile_ranking <- function(data) { + data |> + prepare_avg_best_case_join_table( + "avg_profile_ranking_worst_case", + "avg_profile_ranking_best_case" + ) +} diff --git a/R/best_case_worst_case_avg_reduction_targets.R b/R/best_case_worst_case_avg_reduction_targets.R new file mode 100644 index 0000000..04cd1f5 --- /dev/null +++ b/R/best_case_worst_case_avg_reduction_targets.R @@ -0,0 +1,59 @@ +best_case_worst_case_avg_reduction_targets <- function(data) { + product <- data |> + unnest_product() + + avg_best_case_worst_case_at_product_level <- product |> + prepare_for_join_at_company_level_reduction_targets() + + avg_best_case <- prepare_avg_best_case_join_table_reduction_targets( + avg_best_case_worst_case_at_product_level + ) + avg_worst_case <- prepare_avg_worst_case_join_table_reduction_targets( + avg_best_case_worst_case_at_product_level + ) + + company <- data |> + unnest_company() |> + left_join(avg_best_case, by = c( + col_companies_id(), + "scenario", + "year" + )) |> + left_join(avg_worst_case, by = c( + col_companies_id(), + "scenario", + "year" + )) + + tilt_profile(nest_levels(product, company)) +} + +prepare_for_join_at_company_level_reduction_targets <- function(data) { + data |> + select(all_of(c( + col_companies_id(), + col_scenario(), + col_year(), + "sector_profile_best_case", + "sector_profile_worst_case" + ))) |> + distinct() |> + rename("avg_reduction_targets_best_case" = "sector_profile_best_case", + "avg_reduction_targets_worst_case" = "sector_profile_worst_case") +} + +prepare_avg_worst_case_join_table_reduction_targets <- function(data) { + data |> + prepare_avg_best_case_join_table( + "avg_reduction_targets_best_case", + "avg_reduction_targets_worst_case" + ) +} + +prepare_avg_best_case_join_table_reduction_targets <- function(data) { + data |> + prepare_avg_best_case_join_table( + "avg_reduction_targets_worst_case", + "avg_reduction_targets_best_case" + ) +} diff --git a/R/best_case_worst_case_transition_risk_profile.R b/R/best_case_worst_case_transition_risk_profile.R new file mode 100644 index 0000000..631b745 --- /dev/null +++ b/R/best_case_worst_case_transition_risk_profile.R @@ -0,0 +1,30 @@ +#' Calculates best case and worst case for tranistion risk profile at product level +#' +#' @param data Dataframe. Transition risk profile product level output +#' +#' @return A dataframe +#' @export +#' @keywords internal +best_case_worst_case_transition_risk_profile <- function(data) { + crucial_cols <- c( + col_companies_id(), col_europages_product(), + col_transition_risk_grouped_by(), col_transition_risk_category() + ) + check_crucial_cols(data, crucial_cols) + + best_case_worst_case_impl(data, + col_group_by = col_transition_risk_grouped_by(), + col_risk = col_transition_risk_category(), + col_rank = "transition_risk_score" + + ) +} + +polish_best_case_worst_case_transition_risk_profile <- function(data) { + data |> + rename_with_prefix("transition_risk_profile_", match = c( + "^best_case$", + "^worst_case$", + "^equal_weight$" + )) +} diff --git a/R/best_case_worst_case_transition_risk_profile_at_company_level.R b/R/best_case_worst_case_transition_risk_profile_at_company_level.R new file mode 100644 index 0000000..902c955 --- /dev/null +++ b/R/best_case_worst_case_transition_risk_profile_at_company_level.R @@ -0,0 +1,65 @@ +best_case_worst_case_transition_risk_profile_at_company_level <- function(data) { + product <- data |> + unnest_product() + + avg_best_case_worst_case_at_product_level <- product |> + prepare_for_join_at_company_level_transition_risk() + + avg_best_case <- prepare_avg_best_case_join_table_transition_risk( + avg_best_case_worst_case_at_product_level + ) + avg_worst_case <- prepare_avg_worst_case_join_table_transition_risk( + avg_best_case_worst_case_at_product_level + ) + + company <- data |> + unnest_company() |> + left_join(avg_best_case, by = c(col_companies_id(), + "benchmark_tr_score_avg" = col_transition_risk_grouped_by() + )) |> + left_join(avg_worst_case, by = c(col_companies_id(), + "benchmark_tr_score_avg" = col_transition_risk_grouped_by() + )) |> + polish_transition_risk_best_case_worst_case_at_company_level() + + tilt_profile(nest_levels(product, company)) +} + +prepare_for_join_at_company_level_transition_risk <- function(data) { + data |> + select(all_of(c( + col_companies_id(), + col_transition_risk_grouped_by(), + "transition_risk_profile_best_case", + "transition_risk_profile_worst_case" + ))) |> + distinct() |> + rename("avg_transition_risk_best_case" = "transition_risk_profile_best_case", + "avg_transition_risk_worst_case" = "transition_risk_profile_worst_case") +} + +prepare_avg_worst_case_join_table_transition_risk <- function(data) { + data |> + prepare_avg_best_case_join_table( + "avg_transition_risk_best_case", + "avg_transition_risk_worst_case" + ) +} + +prepare_avg_best_case_join_table_transition_risk <- function(data) { + data |> + prepare_avg_best_case_join_table( + "avg_transition_risk_worst_case", + "avg_transition_risk_best_case" + ) +} + +polish_transition_risk_best_case_worst_case_at_company_level <- function(data) { + rename(data, avg_transition_risk_equal_weight = "transition_risk_score_avg") +} + +prepare_avg_best_case_join_table <- function(data, case1_col, case2_col) { + data |> + select(-all_of(c(case1_col))) |> + filter(!is.na(.data[[case2_col]])) +} diff --git a/R/coefficient_of_variation_transition_risk_profile.R b/R/coefficient_of_variation_transition_risk_profile.R new file mode 100644 index 0000000..26dfa4d --- /dev/null +++ b/R/coefficient_of_variation_transition_risk_profile.R @@ -0,0 +1,133 @@ +coefficient_of_variation_transition_risk_profile <- function(data) { + product <- data |> + unnest_product() + + company <- data |> + unnest_company() |> + add_coefficient_of_variation_transition_risk() |> + polish_coefficient_of_variation_transition_risk() |> + add_coefficient_of_variation_emission_rank() |> + polish_coefficient_of_variation_emission_rank() |> + add_coefficient_of_variation_sector_target() |> + polish_coefficient_of_variation_sector_target() + + tilt_profile(nest_levels(product, company)) +} + +add_coefficient_of_variation_transition_risk <- function(data) { + data |> + add_mean_cov( + "mean_transition_risk", + "avg_transition_risk_equal_weight", + "avg_transition_risk_best_case", + "avg_transition_risk_worst_case" + ) |> + add_standard_deviation_cov( + "standard_deviation_transition_risk", + "mean_transition_risk", + "avg_transition_risk_equal_weight", + "avg_transition_risk_best_case", + "avg_transition_risk_worst_case" + ) |> + add_coefficient_of_variation( + "cov_transition_risk", + "standard_deviation_transition_risk", + "mean_transition_risk" + ) +} + +polish_coefficient_of_variation_transition_risk <- function(data) { + data |> + select(-c("mean_transition_risk", "standard_deviation_transition_risk")) +} + +add_coefficient_of_variation_emission_rank <- function(data) { + data |> + add_mean_cov( + "mean_emission_rank", + "profile_ranking_avg", + "avg_profile_ranking_best_case", + "avg_profile_ranking_worst_case" + ) |> + add_standard_deviation_cov( + "standard_deviation_emission_rank", + "mean_emission_rank", + "profile_ranking_avg", + "avg_profile_ranking_best_case", + "avg_profile_ranking_worst_case" + ) |> + add_coefficient_of_variation( + "cov_emission_rank", + "standard_deviation_emission_rank", + "mean_emission_rank" + ) +} + +polish_coefficient_of_variation_emission_rank <- function(data) { + data |> + select(-c("mean_emission_rank", "standard_deviation_emission_rank")) +} + +add_coefficient_of_variation_sector_target <- function(data) { + data |> + add_mean_cov( + "mean_sector_target", + "reduction_targets_avg", + "avg_reduction_targets_best_case", + "avg_reduction_targets_worst_case" + ) |> + add_standard_deviation_cov( + "standard_deviation_sector_target", + "mean_sector_target", + "reduction_targets_avg", + "avg_reduction_targets_best_case", + "avg_reduction_targets_worst_case" + ) |> + add_coefficient_of_variation( + "cov_sector_target", + "standard_deviation_sector_target", + "mean_sector_target" + ) +} + +polish_coefficient_of_variation_sector_target <- function(data) { + data |> + select(-c("mean_sector_target", "standard_deviation_sector_target")) +} + +add_coefficient_of_variation <- function(data, cov_col, sd_col, mean_col) { + mutate( + data, + {{ cov_col }} := case_when( + is.na(.data[[mean_col]]) ~ NA_real_, + .data[[mean_col]] == 0.0 ~ NA_real_, + TRUE ~ (.data[[sd_col]] / .data[[mean_col]]) * 100 + ) + ) +} + +add_mean_cov <- function(data, mean_col, col1, col2, col3) { + mutate( + data, + {{ mean_col }} := ifelse(is.na(.data[[col1]]), + NA_real_, + (.data[[col1]] + .data[[col2]] + .data[[col3]]) / 3 + ) + ) +} + +# Denominator is `n` and not `n-1` because we are not calculating the standard +# deviation of a sample from whole population. +add_standard_deviation_cov <- function(data, sd_col, mean_col, col1, col2, col3) { + mutate( + data, + {{ sd_col }} := ifelse(is.na(.data[[mean_col]]), + NA_real_, + round(sqrt( + ((.data[[col1]] - .data[[mean_col]])^2 + + (.data[[col2]] - .data[[mean_col]])^2 + + (.data[[col3]] - .data[[mean_col]])^2) / 3 + ), 8) + ) + ) +} diff --git a/R/col-transition_risk_profile.R b/R/col-transition_risk_profile.R index c3a9b28..9239a1f 100644 --- a/R/col-transition_risk_profile.R +++ b/R/col-transition_risk_profile.R @@ -18,14 +18,6 @@ col_subsector <- function() { "subsector" } -col_year <- function() { - "year" -} - -col_scenario <- function() { - "scenario" -} - col_targets <- function() { "reductions" } diff --git a/R/cols-best_case_worst_case.R b/R/cols-best_case_worst_case.R new file mode 100644 index 0000000..328bb56 --- /dev/null +++ b/R/cols-best_case_worst_case.R @@ -0,0 +1,35 @@ +col_companies_id <- function() { + "companies_id" +} + +col_europages_product <- function() { + "ep_product" +} + +col_emission_grouped_by <- function() { + "benchmark" +} + +col_emission_profile <- function() { + "emission_profile" +} + +col_transition_risk_grouped_by <- function() { + "benchmark_tr_score" +} + +col_transition_risk_category <- function() { + "transition_risk_category" +} + +col_scenario <- function() { + "scenario" +} + +col_year <- function() { + "year" +} + +col_sector_profile <- function() { + "sector_profile" +} diff --git a/R/example_data.R b/R/example_data.R new file mode 100644 index 0000000..b9e7aba --- /dev/null +++ b/R/example_data.R @@ -0,0 +1,140 @@ +#' Example input datasets for Transition Risk Score +#' +#' @return A dataframe. +#' @export +#' @keywords internal +#' +#' @examples +#' example_emissions_profile_at_product_level() +#' example_sector_profile_at_product_level() +example_emissions_profile_at_product_level <- function() { + local_options(readr.show_col_types = FALSE) + toy_emissions_profile_products_ecoinvent <- + read_csv(toy_emissions_profile_products_ecoinvent()) + toy_emissions_profile_any_companies <- + read_csv(toy_emissions_profile_any_companies()) + toy_europages_companies <- read_csv(toy_europages_companies()) + toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) + toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) + toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) + toy_isic_name <- read_csv(toy_isic_name()) + + emissions_profile_at_product_level <- profile_emissions( + companies = toy_emissions_profile_any_companies, + co2 = toy_emissions_profile_products_ecoinvent, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) |> + unnest_product() + emissions_profile_at_product_level +} + +#' @export +#' @rdname example_emissions_profile_at_product_level +example_sector_profile_at_product_level <- function() { + local_options(readr.show_col_types = FALSE) + toy_sector_profile_any_scenarios <- + read_csv(toy_sector_profile_any_scenarios()) + toy_sector_profile_companies <- + read_csv(toy_sector_profile_companies()) + toy_europages_companies <- read_csv(toy_europages_companies()) + toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) + toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) + toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) + toy_isic_name <- read_csv(toy_isic_name()) + + sector_profile_at_product_level <- profile_sector( + companies = toy_sector_profile_companies, + scenarios = toy_sector_profile_any_scenarios, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) |> + unnest_product() + sector_profile_at_product_level +} + + +example_best_case_worst_case_transition_risk_profile_product_level <- example_data_factory( + # styler: off + tribble( + ~companies_id, ~ep_product, ~benchmark_tr_score, ~transition_risk_category, ~transition_risk_score, + "any", "one", "1.5C RPS_2030_all", "low", 1.0, + "any", "two", "1.5C RPS_2030_all", "medium", 2.0, + "any", "three", "1.5C RPS_2030_all", "high", 3.0, + ) + # styler: on +) + +example_best_case_worst_case_transition_risk_profile_company_level <- example_data_factory( + # styler: off + tribble( + ~companies_id, ~benchmark_tr_score_avg, ~transition_risk_score_avg, + "any", "1.5C RPS_2030_all", 5.0, + "any", "1.5C RPS_2030_unit", 6.0, + "any", "1.5C RPS_2050_all", 7.0 + ) + # styler: on +) + + +example_best_case_worst_case_profile_ranking_product_level <- example_data_factory( + # styler: off + tribble( + ~companies_id, ~ep_product, ~benchmark, ~emission_profile, ~profile_ranking, + "any", "one", "all", "low", 1.0, + "any", "two", "all", "medium", 2.0, + "any", "three", "all", "high", 3.0 + ) + # styler: on +) + +example_best_case_worst_case_profile_ranking_company_level <- example_data_factory( + # styler: off + tribble( + ~companies_id, ~benchmark, ~profile_ranking_avg, + "any", "all", 5.0, + "any", "unit", 6.0, + "any", "tilt_sector", 7.0 + ) + # styler: on +) + +example_best_case_worst_case_reduction_targets_product_level <- example_data_factory( + # styler: off + tribble( + ~companies_id, ~ep_product, ~scenario_year, ~sector_profile, ~reduction_targets, + "any", "one", "1.5C RPS_2030", "low", 1.0, + "any", "two", "1.5C RPS_2030", "medium", 2.0, + "any", "three", "1.5C RPS_2030", "high", 3.0 + ) + # styler: on +) + +example_best_case_worst_case_reduction_targets_company_level <- example_data_factory( + # styler: off + tribble( + ~companies_id, ~scenario, ~year, ~reduction_targets, + "any", "1.5C RPS", 2030, 1.0, + "any", "1.5C RPS", 2050, 2.0, + "any", "NZ 2050", 2030, 3.0 + ) + # styler: on +) + +example_risk_categories_at_product_level <- example_data_factory( + # styler: off + tribble( + ~companies_id, ~ep_product, ~benchmark_tr_score, ~transition_risk_category, + "any", "a", "all", "low", + "any", "a", "all", "medium", + "any", "a", "all", "high", + "any", "b", "unit", "low", + "any", "b", "unit", "medium", + "any", "b", "unit", "high", + ) + # styler: on +) diff --git a/R/exclude_cols_then_pivot_wider.R b/R/exclude_cols_then_pivot_wider.R new file mode 100644 index 0000000..75ba582 --- /dev/null +++ b/R/exclude_cols_then_pivot_wider.R @@ -0,0 +1,91 @@ +#' Excluding irrelevant columns and duplicates, then pivot from long to wide +#' +#' @param data A data frame to pivot. +#' @param ... Arguments passed to [tidyr::pivot_wider()]. +#' @param exclude_cols A character vector giving regular expressions matching +#' column names to exclude. If lengh > 1, the union is taken. +#' @param avoid_list_cols Logical. Avoid all list-columns, duplicates, and the +#' associated warning? +#' +#' @return A data frame giving the result you get from [tidyr::pivot_wider()] if +#' `data` lacks the excluded columns and the resulting duplicates. +#' @export +#' @keywords internal +#' +#' @examples +#' library(tidyr, warn.conflicts = FALSE) +#' library(dplyr, warn.conflicts = FALSE) +#' +#' # styler: off +#' data <- tribble( +#' ~to_exclude, ~id, ~name, ~value, +#' 1, "id", "a", 1, +#' 2, "id", "a", 1, +#' 1, "id", "b", 2, +#' 2, "id", "b", 2, +#' ) +#' # styler: on +#' +#' # `exclude_cols_then_pivot_wider()` excludes columns and duplicates +#' data |> exclude_cols_then_pivot_wider(exclude_cols = "exclude") +#' +#' # Why is this useful? +#' # `pivot_wider()` defaults to using all columns +#' data |> pivot_wider() +#' +#' # You may specify relevant columns but the result may still have duplicates +#' data |> +#' pivot_wider(id_cols = id, names_from = "name", values_from = "value") |> +#' unnest(c(a, b)) +#' +#' # styler: off +#' data <- tribble( +#' ~id, ~name, ~value, ~to_exclude, ~yields_duplicates, +#' "id", "a", 1, 1, 1, +#' "id", "a", 1, 2, 2 +#' ) +#' # styler: on +#' +#' # `data` may have columns that yield duplicates and thus list-columns +#' with_list_cols <- exclude_cols_then_pivot_wider( +#' data, +#' exclude_cols = "to_exclude", +#' id_cols = "id" +#' ) +#' # You can handle it after the fact +#' with_list_cols |> +#' tidyr::unnest(everything()) |> +#' distinct() +#' +#' # But also you can avoid it with `avoid_list_cols = TRUE` +#' exclude_cols_then_pivot_wider( +#' data, +#' exclude_cols = "to_exclude", +#' id_cols = "id", +#' avoid_list_cols = TRUE +#' ) +exclude_cols_then_pivot_wider <- function(data, + ..., + exclude_cols = NULL, + avoid_list_cols = FALSE) { + pruned <- data |> + select(-matches(exclude_cols)) |> + distinct() + + if (!avoid_list_cols) { + pruned |> pivot_wider(...) + } else { + check_values_fn(...) + + pruned |> + pivot_wider(..., values_fn = list) |> + tidyr::unchop(tidyselect::everything()) |> + distinct() + } +} + +check_values_fn <- function(...) { + if (hasName(list(...), "values_fn")) { + abort("`values_fn` should not be used when `avoid_list_cols = TRUE`.") + } +} diff --git a/R/pivot_wider_transition_risk_profile.R b/R/pivot_wider_transition_risk_profile.R new file mode 100644 index 0000000..cc94074 --- /dev/null +++ b/R/pivot_wider_transition_risk_profile.R @@ -0,0 +1,204 @@ +#' Pivot company-level columns to wide format for indicator "transition risk profile" +#' +#' @param include_co2 Logical. Include `co2_*` columns ? +#' +#' @return A Dataframe +#' @export +#' @keywords internal +#' +#' @examples +#' \dontrun{ +#' library(readr, warn.conflicts = FALSE) +#' library(dplyr, warn.conflicts = FALSE) +#' library(tiltToyData, warn.conflicts = FALSE) +#' library(tiltIndicator) +#' library(tiltIndicatorAfter) +#' +#' restore <- options(list( +#' readr.show_col_types = FALSE, +#' tiltIndicatorAfter.output_co2_footprint = TRUE +#' )) +#' +#' toy_emissions_profile_products_ecoinvent <- read_csv(toy_emissions_profile_products_ecoinvent()) +#' toy_emissions_profile_any_companies <- read_csv(toy_emissions_profile_any_companies()) +#' toy_sector_profile_any_scenarios <- read_csv(toy_sector_profile_any_scenarios()) +#' toy_sector_profile_companies <- read_csv(toy_sector_profile_companies()) +#' toy_europages_companies <- read_csv(toy_europages_companies()) +#' toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) +#' toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) +#' toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) +#' toy_isic_name <- read_csv(toy_isic_name()) +#' toy_all_activities_scenario_sectors <- read_csv(toy_all_activities_scenario_sectors()) +#' +#' toy_emissions_profile <- profile_emissions( +#' companies = toy_emissions_profile_any_companies, +#' co2 = toy_emissions_profile_products_ecoinvent, +#' europages_companies = toy_europages_companies, +#' ecoinvent_activities = toy_ecoinvent_activities, +#' ecoinvent_europages = toy_ecoinvent_europages, +#' isic = toy_isic_name +#' ) +#' +#' toy_sector_profile <- profile_sector( +#' companies = toy_sector_profile_companies, +#' scenarios = toy_sector_profile_any_scenarios, +#' europages_companies = toy_europages_companies, +#' ecoinvent_activities = toy_ecoinvent_activities, +#' ecoinvent_europages = toy_ecoinvent_europages, +#' isic = toy_isic_name +#' ) +#' +#' wide_format <- transition_risk_profile_impl( +#' emissions_profile, +#' sector_profile, +#' co2, +#' all_activities_scenario_sectors, +#' scenarios +#' ) |> +#' add_transition_risk_category_at_company_level() |> +#' best_case_worst_case_transition_risk_profile_at_company_level() |> +#' pivot_wider_transition_risk_profile(include_co2 = TRUE) |> +#' unnest_company() +#' wide_format +#' +#' # Cleanup +#' options(restore) +#' } +pivot_wider_transition_risk_profile <- function(data, include_co2 = FALSE) { + product <- data |> + unnest_product() + + company <- data |> + unnest_company() + + emission_profile_company <- company |> + select_emissions_profile_pivot_cols(include_co2 = include_co2) |> + exclude_subset_cols_then_pivot_wider( + subset_cols = select_subset_emissions_profile_id_cols( + include_co2 = include_co2 + ), + names_from = "emission_profile", + names_prefix = "emission_category_", + values_from = "emission_profile_share" + ) + + sector_profile_company <- company |> + select_sector_profile_pivot_cols() |> + exclude_subset_cols_then_pivot_wider( + subset_cols = select_subset_sector_profile_id_cols(), + names_from = "sector_profile", + names_prefix = "sector_category_", + values_from = "sector_profile_share" + ) + + transition_risk_profile_company <- company |> + select_transition_risk_profile_pivot_cols() |> + exclude_subset_cols_then_pivot_wider( + subset_cols = select_subset_transition_risk_profile_id_cols(), + names_from = "transition_risk_category", + names_prefix = "transition_risk_category_", + values_from = "transition_risk_category_share" + ) + + company <- full_join(emission_profile_company, + sector_profile_company, + by = c( + "companies_id", + "country", + "main_activity" + ), + relationship = "many-to-many" + ) |> + add_benchmark_tr_score_avg() |> + full_join(transition_risk_profile_company, + by = c( + "companies_id", + "country", + "main_activity", + "benchmark_tr_score_avg" + ), + relationship = "many-to-many" + ) |> + distinct() + + tilt_profile(nest_levels(product, company)) +} + +exclude_subset_cols_then_pivot_wider <- function(data, + subset_cols, + names_from, + names_prefix, + values_from) { + data |> + exclude_cols_then_pivot_wider( + exclude_cols = "co2e", + avoid_list_cols = TRUE, + id_cols = subset_cols, + names_from = names_from, + names_prefix = names_prefix, + values_from = values_from + ) +} + +select_subset_emissions_profile_id_cols <- function(data, include_co2 = FALSE) { + c( + "companies_id", + "company_name", + "country", + "main_activity", + "benchmark", + "profile_ranking_avg", + "postcode", + "address", + if (include_co2) "co2_avg", + "min_headcount", + "max_headcount" + ) +} + +select_emissions_profile_pivot_cols <- function(data, include_co2 = FALSE) { + select(data, all_of(c( + select_subset_emissions_profile_id_cols(include_co2 = include_co2), + "emission_profile", + "emission_profile_share" + ))) +} + +select_subset_sector_profile_id_cols <- function(data) { + c( + "companies_id", + "country", + "main_activity", + "scenario", + "year", + "reduction_targets_avg" + ) +} + +select_sector_profile_pivot_cols <- function(data) { + select(data, all_of(c( + select_subset_sector_profile_id_cols(), + "sector_profile", + "sector_profile_share" + ))) +} + +select_subset_transition_risk_profile_id_cols <- function(data) { + c( + "companies_id", + "country", + "main_activity", + "benchmark_tr_score_avg", + "avg_transition_risk_equal_weight", + "avg_transition_risk_best_case", + "avg_transition_risk_worst_case" + ) +} + +select_transition_risk_profile_pivot_cols <- function(data) { + select(data, all_of(c( + select_subset_transition_risk_profile_id_cols(), + "transition_risk_category", + "transition_risk_category_share" + ))) +} diff --git a/R/prepare_webtool_output.R b/R/prepare_webtool_output.R new file mode 100644 index 0000000..929e858 --- /dev/null +++ b/R/prepare_webtool_output.R @@ -0,0 +1,43 @@ +prepare_webtool_output <- function(data, + for_webtool = FALSE, + include_co2 = FALSE) { + if (for_webtool) { + prepare_webtool_output_impl(data, include_co2 = include_co2) + } + else { + data + } +} + +prepare_webtool_output_impl <- function(data, include_co2 = FALSE) { + product <- data |> + unnest_product() |> + select_webtool_cols_at_product_level() + + company <- data |> + unnest_company() |> + select_webtool_cols_at_company_level_wide() |> + rename_webtool_cols_at_company_level_wide() + + if (include_co2) { + product <- product |> + select(-all_of(c("co2_footprint"))) + + company <- company |> + select(-all_of(c("co2e_avg"))) + } + + tilt_profile(nest_levels(product, company)) +} + +polish_transition_risk_profile <- function(data) { + product <- data |> + unnest_product() |> + rename_transition_risk_profile_cols_product() + + company <- data |> + unnest_company() |> + rename_transition_risk_profile_cols_company() + + tilt_profile(nest_levels(product, company)) +} diff --git a/R/relocate_transition_risk_profile_cols.R b/R/relocate_transition_risk_profile_cols.R new file mode 100644 index 0000000..c989280 --- /dev/null +++ b/R/relocate_transition_risk_profile_cols.R @@ -0,0 +1,108 @@ +relocate_transition_risk_profile_cols <- function( + data, + include_co2 = FALSE) { + product <- data |> + unnest_product() |> + relocate_transition_risk_profile_cols_at_product_level( + include_co2 = include_co2 + ) + + company <- data |> + unnest_company() |> + relocate_transition_risk_profile_cols_at_company_level( + include_co2 = include_co2 + ) + + tilt_profile(nest_levels(product, company)) +} + +relocate_transition_risk_profile_cols_at_product_level <- function( + data, + include_co2 = FALSE) { + data |> + relocate( + "companies_id", + "company_name", + "country", + "postcode", + "address", + "main_activity", + "ep_product", + "matched_activity_name", + "matched_reference_product", + "matching_certainty", + if (include_co2) "co2_footprint", + "unit", + "isic_4digit", + "tilt_sector", + "tilt_subsector", + "benchmark", + "co2e_lower", + "co2e_upper", + "profile_ranking", + "emission_profile", + "emissions_profile_equal_weight", + "emissions_profile_best_case", + "emissions_profile_worst_case", + "scenario", + "year", + "reduction_targets", + "sector_profile", + "sector_profile_equal_weight", + "sector_profile_best_case", + "sector_profile_worst_case", + "benchmark_tr_score", + "transition_risk_score", + "transition_risk_low_threshold", + "transition_risk_high_threshold", + "transition_risk_category", + "transition_risk_profile_equal_weight", + "transition_risk_profile_best_case", + "transition_risk_profile_worst_case", + "amount_of_distinct_products", + "amount_of_distinct_products_matched", + "transition_risk_NA_total", + "transition_risk_NA_share", + "min_headcount", + "max_headcount" + ) +} + +relocate_transition_risk_profile_cols_at_company_level <- function( + data, + include_co2 = FALSE) { + data |> + relocate( + "companies_id", + "company_name", + "country", + if (include_co2) "co2_avg", + "benchmark", + "profile_ranking_avg", + "avg_profile_ranking_best_case", + "avg_profile_ranking_worst_case", + "emission_category_low", + "emission_category_medium", + "emission_category_high", + "emission_category_NA", + "scenario", + "year", + "reduction_targets_avg", + "avg_reduction_targets_best_case", + "avg_reduction_targets_worst_case", + "sector_category_low", + "sector_category_medium", + "sector_category_high", + "sector_category_NA", + "benchmark_tr_score_avg", + "avg_transition_risk_equal_weight", + "avg_transition_risk_best_case", + "avg_transition_risk_worst_case", + "transition_risk_NA_share", + "postcode", + "address", + "main_activity", + "min_headcount", + "max_headcount" + ) +} diff --git a/R/round_off_to_4_decimal_places.R b/R/round_off_to_4_decimal_places.R new file mode 100644 index 0000000..ed6b59c --- /dev/null +++ b/R/round_off_to_4_decimal_places.R @@ -0,0 +1,16 @@ +round_off_to_4_decimal_places <- function(data) { + product <- data |> + unnest_product() |> + round_off_to_4_decimal_places_impl() + + company <- data |> + unnest_company() |> + round_off_to_4_decimal_places_impl() + + tilt_profile(nest_levels(product, company)) +} + +round_off_to_4_decimal_places_impl <- function(data) { + data |> + mutate(across(where(is.numeric), ~ round(.x, 4))) +} diff --git a/R/score_transition_risk.R b/R/score_transition_risk.R new file mode 100644 index 0000000..b9d2767 --- /dev/null +++ b/R/score_transition_risk.R @@ -0,0 +1,124 @@ +#' Transition Risk Score +#' +#' Calulate Transition Risk Score at product level and company level +#' +#' @param emissions_profile_at_product_level Dataframe. Emissions profile product level output +#' @param sector_profile_at_product_level Dataframe. Sector profile product level output +#' +#' @family top-level functions +#' +#' @return A dataframe +#' @export +#' +#' @examples +#' library(dplyr) +#' library(readr, warn.conflicts = FALSE) +#' library(tiltToyData) +#' library(tiltIndicator) +#' library(tiltIndicatorAfter) +#' +#' restore <- options(readr.show_col_types = FALSE) +#' +#' emissions_companies <- read_csv(toy_emissions_profile_any_companies()) +#' products <- read_csv(toy_emissions_profile_products_ecoinvent()) +#' europages_companies <- read_csv(toy_europages_companies()) +#' ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) +#' ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) +#' isic_name <- read_csv(toy_isic_name()) +#' +#' emissions_profile_at_product_level <- profile_emissions( +#' companies = emissions_companies, +#' co2 = products, +#' europages_companies = europages_companies, +#' ecoinvent_activities = ecoinvent_activities, +#' ecoinvent_europages = ecoinvent_europages, +#' isic = isic_name +#' ) |> unnest_product() +#' +#' sector_companies <- read_csv(toy_sector_profile_companies()) +#' scenarios <- read_csv(toy_sector_profile_any_scenarios()) +#' +#' sector_profile_at_product_level <- profile_sector( +#' companies = sector_companies, +#' scenarios = scenarios, +#' europages_companies = europages_companies, +#' ecoinvent_activities = ecoinvent_activities, +#' ecoinvent_europages = ecoinvent_europages, +#' isic = isic_name +#' ) |> unnest_product() +#' +#' result <- score_transition_risk(emissions_profile_at_product_level, sector_profile_at_product_level) +#' +#' result |> unnest_product() +#' +#' result |> unnest_company() +#' +#' # Cleanup +#' options(restore) +score_transition_risk <- + function(emissions_profile_at_product_level, + sector_profile_at_product_level) { + union_emissions_sector_rows <- + get_rows_union_for_common_cols( + emissions_profile_at_product_level, + sector_profile_at_product_level + ) + trs_emissions <- + prepare_trs_emissions(emissions_profile_at_product_level) + trs_sector <- + prepare_trs_sector(sector_profile_at_product_level) + + trs_product <- + full_join_emmissions_sector(trs_emissions, trs_sector) |> + add_transition_risk_score( + col_ranking = col_ranking(), + col_target = "reduction_targets" + ) |> + create_benchmarks_tr_score() |> + limit_transition_risk_score_between_0_and_1() |> + select(-all_of(c("scenario_year", "benchmark"))) |> + left_join( + union_emissions_sector_rows, + by = c("companies_id", "ep_product", "activity_uuid_product_uuid"), + relationship = "many-to-many" + ) |> + relocate( + relocate_trs_columns(product_level_trs_column()), + "profile_ranking", + "reduction_targets" + ) |> + distinct() + + trs_company <- trs_product |> + select(common_columns_emissions_sector_at_company_level(), "benchmark_tr_score", product_level_trs_column()) |> + create_trs_average() |> + select(-product_level_trs_column()) |> + relocate(relocate_trs_columns(company_level_trs_avg_column())) |> + rename(benchmark_tr_score_avg = "benchmark_tr_score") |> + distinct() + + nest_levels(trs_product, trs_company) + } + +create_benchmarks_tr_score <- function(data) { + mutate( + data, + benchmark_tr_score = ifelse( + is.na(.data$profile_ranking) | is.na(.data$reduction_targets), + NA, + paste(.data$scenario_year, .data$benchmark, sep = "_") + ) + ) +} + +create_trs_average <- function(data) { + mutate( + data, + transition_risk_score_avg = mean(.data$transition_risk_score, na.rm = TRUE), + .by = c("companies_id", "benchmark_tr_score") + ) +} + +limit_transition_risk_score_between_0_and_1 <- function(data) { + mutate(data, transition_risk_score = pmin(pmax(data$transition_risk_score, 0), 1)) +} diff --git a/R/score_transition_risk_and_polish.R b/R/score_transition_risk_and_polish.R new file mode 100644 index 0000000..1b50c43 --- /dev/null +++ b/R/score_transition_risk_and_polish.R @@ -0,0 +1,222 @@ +#' Add transition risk score and polish the output for delivery +#' +#' @param emissions_profile Nested data frame. The output of +#' `profile_emissions()`. +#' @param sector_profile Nested data frame. The output of `profile_sector()`. +#' @param include_co2 Logical. Include `co2_*` columns ? +#' +#' @return A data frame with the column `companies_id`, and the nested +#' columns`product` and `company` holding the outputs at product and company +#' level. +#' @export +#' @keywords internal +#' +#' @examples +#' library(readr, warn.conflicts = FALSE) +#' library(dplyr, warn.conflicts = FALSE) +#' library(tiltToyData, warn.conflicts = FALSE) +#' library(tiltIndicator) +#' library(tiltIndicatorAfter) +#' +#' set.seed(123) +#' restore <- options(list( +#' readr.show_col_types = FALSE, +#' tiltIndicatorAfter.output_co2_footprint = TRUE +#' )) +#' +#' toy_emissions_profile_products_ecoinvent <- read_csv(toy_emissions_profile_products_ecoinvent()) +#' toy_emissions_profile_any_companies <- read_csv(toy_emissions_profile_any_companies()) +#' toy_sector_profile_any_scenarios <- read_csv(toy_sector_profile_any_scenarios()) +#' toy_sector_profile_companies <- read_csv(toy_sector_profile_companies()) +#' toy_europages_companies <- read_csv(toy_europages_companies()) +#' toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) +#' toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) +#' toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) +#' toy_isic_name <- read_csv(toy_isic_name()) +#' +#' emissions_profile <- profile_emissions( +#' companies = toy_emissions_profile_any_companies, +#' co2 = toy_emissions_profile_products_ecoinvent, +#' europages_companies = toy_europages_companies, +#' ecoinvent_activities = toy_ecoinvent_activities, +#' ecoinvent_europages = toy_ecoinvent_europages, +#' isic = toy_isic_name +#' ) +#' +#' sector_profile <- profile_sector( +#' companies = toy_sector_profile_companies, +#' scenarios = toy_sector_profile_any_scenarios, +#' europages_companies = toy_europages_companies, +#' ecoinvent_activities = toy_ecoinvent_activities, +#' ecoinvent_europages = toy_ecoinvent_europages, +#' isic = toy_isic_name +#' ) +#' +#' result <- score_transition_risk_and_polish(emissions_profile, +#' sector_profile, +#' include_co2 = TRUE +#' ) +#' +#' result |> unnest_product() +#' +#' result |> unnest_company() +#' +#' # Cleanup +#' options(restore) +score_transition_risk_and_polish <- function(emissions_profile, + sector_profile, + include_co2 = FALSE) { + transition_risk_score <- score_transition_risk( + unnest_product(emissions_profile), + unnest_product(sector_profile) + ) + + if (include_co2) { + hint <- "Do you need `options(tiltIndicatorAfter.output_co2_footprint = TRUE)`?" + unnest_product(emissions_profile) |> check_col("co2_footprint", hint) + } + + select_emissions_profile_product <- unnest_product(emissions_profile) |> + select( + c( + "companies_id", + "country", + "main_activity", + "ep_product", + "postcode", + "address", + "activity_uuid_product_uuid", + "matched_activity_name", + "matched_reference_product", + "unit", + "co2e_lower", + "co2e_upper", + "emission_profile", + "benchmark", + "profile_ranking", + "tilt_sector", + "tilt_subsector", + "min_headcount", + "max_headcount", + "emissions_profile_best_case", + "emissions_profile_worst_case", + "isic_4digit", + "matching_certainty", + "company_name", + "emissions_profile_equal_weight", + if (include_co2) "co2_footprint" + ) + ) + select_sector_profile_product <- unnest_product(sector_profile) |> + select( + c( + "companies_id", + "ep_product", + "sector_profile", + "scenario", + "year", + "reduction_targets", + "tilt_sector", + "tilt_subsector", + "isic_4digit", + "sector_profile_best_case", + "sector_profile_worst_case", + "sector_profile_equal_weight" + ) + ) + + select_transition_risk_score_product <- unnest_product(transition_risk_score) |> + select(c( + "companies_id", + "ep_product", + "benchmark_tr_score", + "transition_risk_score" + )) + + out_product <- select_emissions_profile_product |> + left_join( + select_sector_profile_product, + relationship = "many-to-many", + by = c("companies_id", "ep_product"), + suffix = c(".emissions", ".sector") + ) |> + coalesce_common_col("tilt_sector", "emissions", "sector") |> + coalesce_common_col("tilt_subsector", "emissions", "sector") |> + coalesce_common_col("isic_4digit", "emissions", "sector") |> + mutate(benchmark_tr_score = ifelse( + is.na(.data$profile_ranking) | is.na(.data$reduction_targets), + NA_character_, + paste(.data$scenario, .data$year, .data$benchmark, sep = "_") + )) |> + left_join( + select_transition_risk_score_product, + by = c("companies_id", "ep_product", "benchmark_tr_score"), + relationship = "many-to-many" + ) |> + distinct() + + select_emissions_profile_company <- unnest_company(emissions_profile) |> + select( + c( + "companies_id", + "company_name", + "country", + "main_activity", + "postcode", + "address", + "benchmark", + "min_headcount", + "max_headcount", + "emission_profile", + "emission_profile_share", + "profile_ranking_avg", + if (include_co2) "co2_avg" + ) + ) + + select_sector_profile_company <- unnest_company(sector_profile) |> + select(c("companies_id", "sector_profile", "sector_profile_share", "scenario", "year", "reduction_targets_avg")) + + select_transition_risk_score_company <- unnest_company(transition_risk_score) |> + select( + c( + "companies_id", + "benchmark_tr_score_avg", + "transition_risk_score_avg" + ) + ) + + out_company <- select_emissions_profile_company |> + left_join( + select_sector_profile_company, + relationship = "many-to-many", + by = c("companies_id") + ) |> + add_benchmark_tr_score_avg() |> + left_join( + select_transition_risk_score_company, + by = c("companies_id", "benchmark_tr_score_avg") + ) |> + distinct() + + nest_levels(out_product, out_company) +} + +add_benchmark_tr_score_avg <- function(data) { + mutate( + data, + benchmark_tr_score_avg = ifelse( + is.na(.data$profile_ranking_avg) | is.na(.data$reduction_targets_avg), + NA_character_, + paste(.data$scenario, .data$year, .data$benchmark, sep = "_") + ) + ) +} + +coalesce_common_col <- function(data, col, suffix1, suffix2) { + col_suffix1 = paste(col, suffix1, sep = ".") + col_suffix2 = paste(col, suffix2, sep = ".") + data |> + mutate({{ col }} := coalesce(.data[[col_suffix1]], .data[[col_suffix2]])) |> + select(-all_of(c(col_suffix1, col_suffix2))) +} diff --git a/R/tiltTransitionRisk-options.R b/R/tiltTransitionRisk-options.R new file mode 100644 index 0000000..ba23938 --- /dev/null +++ b/R/tiltTransitionRisk-options.R @@ -0,0 +1,62 @@ +#' tiltTransitionRisk options +#' +#' @description +#' These options are meant to be used mainly by developers or analysts while +#' testing the code or creating data: +#' * `tiltIndicatorAfter.output_co2_footprint`: +#' * At product level it outputs licensed column `co2_footprint`. +#' * At company level it outputs the column `co2_avg` (average `co2_footprint` +#' by `companies_id`). +#' * `tiltIndicatorAfter.verbose`: Controls verbosity. +#' +#' @keywords internal +#' @name tiltIndicatorAfter_options +#' +#' @examples +#' library(readr, warn.conflicts = FALSE) +#' library(dplyr, warn.conflicts = FALSE) +#' library(withr) +#' library(tiltToyData) +#' library(tiltIndicator) +#' library(tiltIndicatorAfter) +#' +#' set.seed(1) +#' +#' restore <- options(list( +#' readr.show_col_types = FALSE, +#' tiltIndicatorAfter.verbose = TRUE, +#' tiltIndicatorAfter.output_co2_footprint = TRUE +#' )) +#' +#' companies <- read_csv(toy_emissions_profile_any_companies()) +#' products <- read_csv(toy_emissions_profile_products_ecoinvent()) +#' europages_companies <- read_csv(toy_europages_companies()) +#' ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) +#' ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) +#' isic_name <- read_csv(toy_isic_name()) +#' +#' result <- profile_emissions( +#' companies, +#' products, +#' europages_companies = europages_companies, +#' ecoinvent_activities = ecoinvent_activities, +#' ecoinvent_europages = ecoinvent_europages, +#' isic = isic_name +#' ) +#' +#' result |> +#' unnest_product() |> +#' select(matches(c("co2"))) +#' +#' result |> +#' unnest_company() |> +#' select(matches(c("co2"))) +NULL + +option_output_co2_footprint <- function() { + getOption("tiltIndicatorAfter.output_co2_footprint", default = FALSE) +} + +option_verbose <- function() { + getOption("tiltIndicatorAfter.verbose", default = TRUE) +} diff --git a/R/tiltTransitionRisk-package.R b/R/tiltTransitionRisk-package.R index 212b01e..5c16513 100644 --- a/R/tiltTransitionRisk-package.R +++ b/R/tiltTransitionRisk-package.R @@ -3,24 +3,78 @@ ## usethis namespace: start #' @importFrom dplyr .data +#' @importFrom dplyr across #' @importFrom dplyr all_of +#' @importFrom dplyr arrange +#' @importFrom dplyr bind_rows +#' @importFrom dplyr case_when +#' @importFrom dplyr coalesce #' @importFrom dplyr distinct #' @importFrom dplyr filter #' @importFrom dplyr full_join +#' @importFrom dplyr left_join #' @importFrom dplyr mutate +#' @importFrom dplyr n_distinct +#' @importFrom dplyr relocate +#' @importFrom dplyr rename +#' @importFrom dplyr rename_with #' @importFrom dplyr select +#' @importFrom dplyr summarise +#' @importFrom dplyr where #' @importFrom glue glue #' @importFrom purrr walk #' @importFrom readr read_csv +#' @importFrom rlang := +#' @importFrom rlang .data #' @importFrom rlang abort +#' @importFrom rlang as_name +#' @importFrom rlang ensym #' @importFrom stats quantile +#' @importFrom tibble tibble #' @importFrom tibble tribble +#' @importFrom tidyr pivot_wider +#' @importFrom tidyselect all_of +#' @importFrom tidyselect any_of +#' @importFrom tidyselect matches #' @importFrom tiltIndicator categorize_risk +#' @importFrom tiltIndicator epa_at_company_level #' @importFrom tiltIndicator epa_compute_profile_ranking +#' @importFrom tiltIndicator example_data_factory +#' @importFrom tiltIndicator insert_row_with_na_in_risk_category +#' @importFrom tiltIndicator nest_levels #' @importFrom tiltIndicator spa_compute_profile_ranking +#' @importFrom tiltIndicator tilt_profile +#' @importFrom tiltIndicator unnest_company +#' @importFrom tiltIndicator unnest_product +#' @importFrom tiltIndicatorAfter best_case_worst_case_emission_profile +#' @importFrom tiltIndicatorAfter best_case_worst_case_impl +#' @importFrom tiltIndicatorAfter best_case_worst_case_sector_profile +#' @importFrom tiltIndicatorAfter polish_best_case_worst_case +#' @importFrom tiltIndicatorAfter profile_emissions +#' @importFrom tiltIndicatorAfter profile_sector +#' @importFrom tiltIndicatorAfter rename_with_prefix +#' @importFrom tiltPolish rename_transition_risk_profile_cols_company +#' @importFrom tiltPolish rename_transition_risk_profile_cols_product +#' @importFrom tiltPolish rename_webtool_cols_at_company_level_wide +#' @importFrom tiltPolish select_webtool_cols_at_company_level_wide +#' @importFrom tiltPolish select_webtool_cols_at_product_level +#' @importFrom tiltToyData toy_ecoinvent_activities +#' @importFrom tiltToyData toy_ecoinvent_europages +#' @importFrom tiltToyData toy_ecoinvent_inputs +#' @importFrom tiltToyData toy_emissions_profile_any_companies +#' @importFrom tiltToyData toy_emissions_profile_products #' @importFrom tiltToyData toy_emissions_profile_products_ecoinvent +#' @importFrom tiltToyData toy_emissions_profile_upstream_products +#' @importFrom tiltToyData toy_emissions_profile_upstream_products_ecoinvent +#' @importFrom tiltToyData toy_europages_companies +#' @importFrom tiltToyData toy_isic_name #' @importFrom tiltToyData toy_sector_profile_any_scenarios #' @importFrom tiltToyData toy_sector_profile_companies +#' @importFrom tiltToyData toy_sector_profile_upstream_companies +#' @importFrom tiltToyData toy_sector_profile_upstream_products +#' @importFrom utils hasName #' @importFrom utils write.csv +#' @importFrom withr local_options +#' @importFrom withr local_seed ## usethis namespace: end NULL diff --git a/R/transition_risk_profile.R b/R/transition_risk_profile.R new file mode 100644 index 0000000..83a0520 --- /dev/null +++ b/R/transition_risk_profile.R @@ -0,0 +1,185 @@ +#' Calculate the indicator "transition risk profile" +#' +#' Adds the risk classification to calculated transition risk scores from +#' emission profile and sector profile indicator. +#' +#' @param emissions_profile Nested data frame. The output of +#' `profile_emissions()`. +#' @param sector_profile Nested data frame. The output of `profile_sector()`. +#' @param co2 A dataframe +#' @param all_activities_scenario_sectors A dataframe +#' @param scenarios A dataframe +#' @param for_webtool Logical. Is it output for webtool or not? +#' +#' @return A data frame with the column `companies_id`, and the nested +#' columns`product` and `company` holding the outputs at product and company +#' level. +#' @export +#' +#' @family top-level functions +#' @family profile functions +#' +#' @examples +#' library(readr, warn.conflicts = FALSE) +#' library(dplyr, warn.conflicts = FALSE) +#' library(tiltToyData, warn.conflicts = FALSE) +#' library(tiltIndicator) +#' library(tiltIndicatorAfter) +#' +#' set.seed(123) +#' restore <- options(list( +#' readr.show_col_types = FALSE, +#' tiltIndicatorAfter.output_co2_footprint = TRUE +#' )) +#' +#' toy_emissions_profile_products_ecoinvent <- read_csv(toy_emissions_profile_products_ecoinvent()) +#' toy_emissions_profile_any_companies <- read_csv(toy_emissions_profile_any_companies()) +#' toy_sector_profile_any_scenarios <- read_csv(toy_sector_profile_any_scenarios()) +#' toy_sector_profile_companies <- read_csv(toy_sector_profile_companies()) +#' toy_europages_companies <- read_csv(toy_europages_companies()) +#' toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) +#' toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) +#' toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) +#' toy_isic_name <- read_csv(toy_isic_name()) +#' toy_all_activities_scenario_sectors <- read_csv(toy_all_activities_scenario_sectors()) +#' +#' toy_emissions_profile <- profile_emissions( +#' companies = toy_emissions_profile_any_companies, +#' co2 = toy_emissions_profile_products_ecoinvent, +#' europages_companies = toy_europages_companies, +#' ecoinvent_activities = toy_ecoinvent_activities, +#' ecoinvent_europages = toy_ecoinvent_europages, +#' isic = toy_isic_name +#' ) +#' +#' toy_sector_profile <- profile_sector( +#' companies = toy_sector_profile_companies, +#' scenarios = toy_sector_profile_any_scenarios, +#' europages_companies = toy_europages_companies, +#' ecoinvent_activities = toy_ecoinvent_activities, +#' ecoinvent_europages = toy_ecoinvent_europages, +#' isic = toy_isic_name +#' ) +#' +#' output <- transition_risk_profile( +#' emissions_profile = toy_emissions_profile, +#' sector_profile = toy_sector_profile, +#' co2 = toy_emissions_profile_products_ecoinvent, +#' all_activities_scenario_sectors = toy_all_activities_scenario_sectors, +#' scenarios = toy_sector_profile_any_scenarios, +#' for_webtool = FALSE +#' ) +#' +#' output |> unnest_product() +#' +#' output |> unnest_company() +transition_risk_profile <- function(emissions_profile, + sector_profile, + co2, + all_activities_scenario_sectors, + scenarios, + for_webtool = FALSE) { + transition_risk_profile_impl( + emissions_profile, + sector_profile, + co2, + all_activities_scenario_sectors, + scenarios + ) |> + add_transition_risk_category_at_company_level() |> + best_case_worst_case_transition_risk_profile_at_company_level() |> + pivot_wider_transition_risk_profile( + include_co2 = option_output_co2_footprint() + ) |> + best_case_worst_case_avg_profile_ranking() |> + best_case_worst_case_avg_reduction_targets() |> + add_transition_risk_NA_share() |> + relocate_transition_risk_profile_cols( + include_co2 = option_output_co2_footprint() + ) |> + round_off_to_4_decimal_places() |> + coefficient_of_variation_transition_risk_profile() |> + polish_transition_risk_profile() |> + prepare_webtool_output( + for_webtool = for_webtool, + include_co2 = option_output_co2_footprint() + ) |> + remove_case3_companies() +} + +transition_risk_profile_impl <- function(emissions_profile, + sector_profile, + co2, + all_activities_scenario_sectors, + scenarios) { + transition_risk_scores <- score_transition_risk_and_polish(emissions_profile, + sector_profile, + include_co2 = option_output_co2_footprint() + ) + transition_risk_thresholds <- add_thresholds_transition_risk( + co2, + all_activities_scenario_sectors, + scenarios + ) |> + select_crucial_threshold_cols() + + product <- transition_risk_scores |> + unnest_product() |> + left_join(transition_risk_thresholds, by = c( + "benchmark_tr_score", + "activity_uuid_product_uuid" + )) |> + add_transition_risk_category_at_product_level() |> + best_case_worst_case_transition_risk_profile() |> + polish_best_case_worst_case() |> + polish_best_case_worst_case_transition_risk_profile() + + company <- transition_risk_scores |> + unnest_company() |> + arrange_transition_risk_at_company_level() + + tilt_profile(nest_levels(product, company)) +} + +arrange_transition_risk_at_company_level <- function(data) { + arrange(data, .data$companies_id, .data$benchmark_tr_score_avg) +} + +select_crucial_threshold_cols <- function(data) { + select(data, all_of(c( + "activity_uuid_product_uuid", "benchmark_tr_score", + "transition_risk_low_threshold", "transition_risk_high_threshold" + ))) +} + +remove_case3_companies <- function(data) { + product <- data |> + unnest_product() + + company <- data |> + unnest_company() + + case_3_companies <- identify_case3_companies(product) + + final_product <- product |> + filter(!(.data$companies_id %in% unique(case_3_companies$companies_id))) |> + distinct() + + final_company <- company |> + filter(!(.data$companies_id %in% unique(case_3_companies$companies_id))) |> + distinct() + + tilt_profile(nest_levels(final_product, final_company)) +} + +identify_case3_companies <- function(data) { + # To identify which companies belong to Case 3, please follow this link: + # https://github.com/2DegreesInvesting/TiltDevProjectMGMT/issues/169#issuecomment-2284344632 + data |> + mutate( + check = + all(is.na(.data$sector_target) & is.na(.data$matched_activity_name)), + .by = col_companies_id() + ) |> + filter(.data$check) +} diff --git a/R/utils-score_transition_risk.R b/R/utils-score_transition_risk.R new file mode 100644 index 0000000..c3789ea --- /dev/null +++ b/R/utils-score_transition_risk.R @@ -0,0 +1,127 @@ +prepare_trs_emissions <- function(data) { + select( + data, + c( + "companies_id", + "benchmark", + "profile_ranking", + "ep_product", + "activity_uuid_product_uuid" + ) + ) +} + +prepare_trs_sector <- function(data) { + data |> + select( + c( + "companies_id", + "scenario", + "year", + "reduction_targets", + "ep_product", + "activity_uuid_product_uuid" + ) + ) |> + mutate(scenario_year = paste(.data$scenario, .data$year, sep = "_")) |> + select(-c("scenario", "year")) +} + +full_join_emmissions_sector <- function(emissions, sector) { + full_join( + emissions, + sector, + by = c("companies_id", "ep_product", "activity_uuid_product_uuid"), + relationship = "many-to-many" + ) +} + +get_rows_union_for_common_cols <- + function(emissions_at_product_level, + sector_at_product_level) { + emission_common_columns <- emissions_at_product_level |> + select(common_columns_emissions_sector_at_product_level()) |> + distinct() + + sector_common_columns <- sector_at_product_level |> + select(common_columns_emissions_sector_at_product_level()) |> + distinct() + + distinct(bind_rows(emission_common_columns, sector_common_columns)) + } + +relocate_trs_columns <- function(columns) { + c( + "companies_id", + "company_name", + "country", + "benchmark_tr_score", + columns + ) +} + +product_level_trs_column <- function() { + c("transition_risk_score") +} + +company_level_trs_avg_column <- function() { + c("transition_risk_score_avg") +} + +trs_company_columns <- function() { + c( + common_columns_emissions_sector_at_company_level(), + "benchmark_tr_score_avg" + ) +} + +trs_product_output_columns <- function() { + c( + common_columns_emissions_sector_at_product_level(), + product_level_trs_column(), + "profile_ranking", + "reduction_targets", + "benchmark_tr_score" + ) +} + +trs_company_output_columns <- function() { + c(trs_company_columns(), company_level_trs_avg_column()) +} + +common_columns_emissions_sector_at_product_level <- function() { + c( + "companies_id", + "company_name", + "country", + "ep_product", + "matched_activity_name", + "matched_reference_product", + "unit", + "multi_match", + "matching_certainty", + "matching_certainty_company_average", + "company_city", + "postcode", + "address", + "main_activity", + "activity_uuid_product_uuid", + "tilt_sector", + "tilt_subsector", + "isic_4digit", + "isic_4digit_name", + "ei_geography" + ) +} + +common_columns_emissions_sector_at_company_level <- function() { + c( + "companies_id", + "company_name", + "country", + "company_city", + "postcode", + "address", + "main_activity" + ) +} diff --git a/R/utils.R b/R/utils.R new file mode 100644 index 0000000..1a61724 --- /dev/null +++ b/R/utils.R @@ -0,0 +1,12 @@ +#' @examples +#' this_data <- tibble(x = 1) +#' this_data |> check_col("y", hint = "Did you forget something?") +#' @noRd +check_col <- function(data, col, hint = NULL) { + if (!hasName(data, col)) { + label <- deparse(substitute(data)) + abort(c(glue("`{label}` must have the column `{col}`."), i = hint)) + } + + invisible(data) +} diff --git a/man/add_benchmark_tr_score.Rd b/man/add_benchmark_tr_score.Rd index 77621bb..6125e35 100644 --- a/man/add_benchmark_tr_score.Rd +++ b/man/add_benchmark_tr_score.Rd @@ -13,9 +13,9 @@ add_benchmark_tr_score( \arguments{ \item{data}{Dataframe.} -\item{profile_ranking}{Dataframe column.} +\item{col_ranking}{Dataframe column.} -\item{reduction_targets}{Dataframe column.} +\item{col_target}{Dataframe column.} } \description{ Calulate \code{benchmark_tr_score} column diff --git a/man/add_transition_risk_category.Rd b/man/add_transition_risk_category_at_product_level.Rd similarity index 68% rename from man/add_transition_risk_category.Rd rename to man/add_transition_risk_category_at_product_level.Rd index 48d7472..fd2e839 100644 --- a/man/add_transition_risk_category.Rd +++ b/man/add_transition_risk_category_at_product_level.Rd @@ -1,10 +1,10 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/add_transition_risk_category.R -\name{add_transition_risk_category} -\alias{add_transition_risk_category} +% Please edit documentation in R/add_transition_risk_category_at_product_level.R +\name{add_transition_risk_category_at_product_level} +\alias{add_transition_risk_category_at_product_level} \title{Adds transition risk categories for transition risk scores} \usage{ -add_transition_risk_category(data) +add_transition_risk_category_at_product_level(data) } \arguments{ \item{data}{A dataframe} @@ -31,7 +31,7 @@ transition_risk_thresholds <- add_thresholds_transition_risk( scenarios ) -output <- add_transition_risk_category(transition_risk_thresholds) +output <- add_transition_risk_category_at_product_level(transition_risk_thresholds) output } \keyword{internal} diff --git a/man/add_transition_risk_score.Rd b/man/add_transition_risk_score.Rd index 0c6671f..fe6c0ce 100644 --- a/man/add_transition_risk_score.Rd +++ b/man/add_transition_risk_score.Rd @@ -13,9 +13,9 @@ add_transition_risk_score( \arguments{ \item{data}{Dataframe.} -\item{profile_ranking}{Dataframe column.} +\item{col_ranking}{Dataframe column.} -\item{reduction_targets}{Dataframe column.} +\item{col_target}{Dataframe column.} } \description{ Calulate \code{transition_risk_score} column diff --git a/man/best_case_worst_case_transition_risk_profile.Rd b/man/best_case_worst_case_transition_risk_profile.Rd new file mode 100644 index 0000000..371bac4 --- /dev/null +++ b/man/best_case_worst_case_transition_risk_profile.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/best_case_worst_case_transition_risk_profile.R +\name{best_case_worst_case_transition_risk_profile} +\alias{best_case_worst_case_transition_risk_profile} +\title{Calculates best case and worst case for tranistion risk profile at product level} +\usage{ +best_case_worst_case_transition_risk_profile(data) +} +\arguments{ +\item{data}{Dataframe. Transition risk profile product level output} +} +\value{ +A dataframe +} +\description{ +Calculates best case and worst case for tranistion risk profile at product level +} +\keyword{internal} diff --git a/man/example_emissions_profile_at_product_level.Rd b/man/example_emissions_profile_at_product_level.Rd new file mode 100644 index 0000000..475a211 --- /dev/null +++ b/man/example_emissions_profile_at_product_level.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/example_data.R +\name{example_emissions_profile_at_product_level} +\alias{example_emissions_profile_at_product_level} +\alias{example_sector_profile_at_product_level} +\title{Example input datasets for Transition Risk Score} +\usage{ +example_emissions_profile_at_product_level() + +example_sector_profile_at_product_level() +} +\value{ +A dataframe. +} +\description{ +Example input datasets for Transition Risk Score +} +\examples{ +example_emissions_profile_at_product_level() +example_sector_profile_at_product_level() +} +\keyword{internal} diff --git a/man/exclude_cols_then_pivot_wider.Rd b/man/exclude_cols_then_pivot_wider.Rd new file mode 100644 index 0000000..754dd1e --- /dev/null +++ b/man/exclude_cols_then_pivot_wider.Rd @@ -0,0 +1,85 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/exclude_cols_then_pivot_wider.R +\name{exclude_cols_then_pivot_wider} +\alias{exclude_cols_then_pivot_wider} +\title{Excluding irrelevant columns and duplicates, then pivot from long to wide} +\usage{ +exclude_cols_then_pivot_wider( + data, + ..., + exclude_cols = NULL, + avoid_list_cols = FALSE +) +} +\arguments{ +\item{data}{A data frame to pivot.} + +\item{...}{Arguments passed to \code{\link[tidyr:pivot_wider]{tidyr::pivot_wider()}}.} + +\item{exclude_cols}{A character vector giving regular expressions matching +column names to exclude. If lengh > 1, the union is taken.} + +\item{avoid_list_cols}{Logical. Avoid all list-columns, duplicates, and the +associated warning?} +} +\value{ +A data frame giving the result you get from \code{\link[tidyr:pivot_wider]{tidyr::pivot_wider()}} if +\code{data} lacks the excluded columns and the resulting duplicates. +} +\description{ +Excluding irrelevant columns and duplicates, then pivot from long to wide +} +\examples{ +library(tidyr, warn.conflicts = FALSE) +library(dplyr, warn.conflicts = FALSE) + +# styler: off +data <- tribble( + ~to_exclude, ~id, ~name, ~value, + 1, "id", "a", 1, + 2, "id", "a", 1, + 1, "id", "b", 2, + 2, "id", "b", 2, +) +# styler: on + +# `exclude_cols_then_pivot_wider()` excludes columns and duplicates +data |> exclude_cols_then_pivot_wider(exclude_cols = "exclude") + +# Why is this useful? +# `pivot_wider()` defaults to using all columns +data |> pivot_wider() + +# You may specify relevant columns but the result may still have duplicates +data |> + pivot_wider(id_cols = id, names_from = "name", values_from = "value") |> + unnest(c(a, b)) + +# styler: off +data <- tribble( + ~id, ~name, ~value, ~to_exclude, ~yields_duplicates, + "id", "a", 1, 1, 1, + "id", "a", 1, 2, 2 +) +# styler: on + +# `data` may have columns that yield duplicates and thus list-columns +with_list_cols <- exclude_cols_then_pivot_wider( + data, + exclude_cols = "to_exclude", + id_cols = "id" +) +# You can handle it after the fact +with_list_cols |> + tidyr::unnest(everything()) |> + distinct() + +# But also you can avoid it with `avoid_list_cols = TRUE` +exclude_cols_then_pivot_wider( + data, + exclude_cols = "to_exclude", + id_cols = "id", + avoid_list_cols = TRUE +) +} +\keyword{internal} diff --git a/man/pivot_wider_transition_risk_profile.Rd b/man/pivot_wider_transition_risk_profile.Rd new file mode 100644 index 0000000..f160b69 --- /dev/null +++ b/man/pivot_wider_transition_risk_profile.Rd @@ -0,0 +1,77 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/pivot_wider_transition_risk_profile.R +\name{pivot_wider_transition_risk_profile} +\alias{pivot_wider_transition_risk_profile} +\title{Pivot company-level columns to wide format for indicator "transition risk profile"} +\usage{ +pivot_wider_transition_risk_profile(data, include_co2 = FALSE) +} +\arguments{ +\item{include_co2}{Logical. Include \verb{co2_*} columns ?} +} +\value{ +A Dataframe +} +\description{ +Pivot company-level columns to wide format for indicator "transition risk profile" +} +\examples{ +\dontrun{ +library(readr, warn.conflicts = FALSE) +library(dplyr, warn.conflicts = FALSE) +library(tiltToyData, warn.conflicts = FALSE) +library(tiltIndicator) +library(tiltIndicatorAfter) + +restore <- options(list( + readr.show_col_types = FALSE, + tiltIndicatorAfter.output_co2_footprint = TRUE +)) + +toy_emissions_profile_products_ecoinvent <- read_csv(toy_emissions_profile_products_ecoinvent()) +toy_emissions_profile_any_companies <- read_csv(toy_emissions_profile_any_companies()) +toy_sector_profile_any_scenarios <- read_csv(toy_sector_profile_any_scenarios()) +toy_sector_profile_companies <- read_csv(toy_sector_profile_companies()) +toy_europages_companies <- read_csv(toy_europages_companies()) +toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) +toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) +toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) +toy_isic_name <- read_csv(toy_isic_name()) +toy_all_activities_scenario_sectors <- read_csv(toy_all_activities_scenario_sectors()) + +toy_emissions_profile <- profile_emissions( + companies = toy_emissions_profile_any_companies, + co2 = toy_emissions_profile_products_ecoinvent, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name +) + +toy_sector_profile <- profile_sector( + companies = toy_sector_profile_companies, + scenarios = toy_sector_profile_any_scenarios, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name +) + +wide_format <- transition_risk_profile_impl( + emissions_profile, + sector_profile, + co2, + all_activities_scenario_sectors, + scenarios +) |> + add_transition_risk_category_at_company_level() |> + best_case_worst_case_transition_risk_profile_at_company_level() |> + pivot_wider_transition_risk_profile(include_co2 = TRUE) |> + unnest_company() +wide_format + +# Cleanup +options(restore) +} +} +\keyword{internal} diff --git a/man/score_transition_risk.Rd b/man/score_transition_risk.Rd new file mode 100644 index 0000000..a409946 --- /dev/null +++ b/man/score_transition_risk.Rd @@ -0,0 +1,73 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/score_transition_risk.R +\name{score_transition_risk} +\alias{score_transition_risk} +\title{Transition Risk Score} +\usage{ +score_transition_risk( + emissions_profile_at_product_level, + sector_profile_at_product_level +) +} +\arguments{ +\item{emissions_profile_at_product_level}{Dataframe. Emissions profile product level output} + +\item{sector_profile_at_product_level}{Dataframe. Sector profile product level output} +} +\value{ +A dataframe +} +\description{ +Calulate Transition Risk Score at product level and company level +} +\examples{ +library(dplyr) +library(readr, warn.conflicts = FALSE) +library(tiltToyData) +library(tiltIndicator) +library(tiltIndicatorAfter) + +restore <- options(readr.show_col_types = FALSE) + +emissions_companies <- read_csv(toy_emissions_profile_any_companies()) +products <- read_csv(toy_emissions_profile_products_ecoinvent()) +europages_companies <- read_csv(toy_europages_companies()) +ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) +ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) +isic_name <- read_csv(toy_isic_name()) + +emissions_profile_at_product_level <- profile_emissions( + companies = emissions_companies, + co2 = products, + europages_companies = europages_companies, + ecoinvent_activities = ecoinvent_activities, + ecoinvent_europages = ecoinvent_europages, + isic = isic_name +) |> unnest_product() + +sector_companies <- read_csv(toy_sector_profile_companies()) +scenarios <- read_csv(toy_sector_profile_any_scenarios()) + +sector_profile_at_product_level <- profile_sector( + companies = sector_companies, + scenarios = scenarios, + europages_companies = europages_companies, + ecoinvent_activities = ecoinvent_activities, + ecoinvent_europages = ecoinvent_europages, + isic = isic_name +) |> unnest_product() + +result <- score_transition_risk(emissions_profile_at_product_level, sector_profile_at_product_level) + +result |> unnest_product() + +result |> unnest_company() + +# Cleanup +options(restore) +} +\seealso{ +Other top-level functions: +\code{\link{transition_risk_profile}()} +} +\concept{top-level functions} diff --git a/man/score_transition_risk_and_polish.Rd b/man/score_transition_risk_and_polish.Rd new file mode 100644 index 0000000..cc0843c --- /dev/null +++ b/man/score_transition_risk_and_polish.Rd @@ -0,0 +1,82 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/score_transition_risk_and_polish.R +\name{score_transition_risk_and_polish} +\alias{score_transition_risk_and_polish} +\title{Add transition risk score and polish the output for delivery} +\usage{ +score_transition_risk_and_polish( + emissions_profile, + sector_profile, + include_co2 = FALSE +) +} +\arguments{ +\item{emissions_profile}{Nested data frame. The output of +\code{profile_emissions()}.} + +\item{sector_profile}{Nested data frame. The output of \code{profile_sector()}.} + +\item{include_co2}{Logical. Include \verb{co2_*} columns ?} +} +\value{ +A data frame with the column \code{companies_id}, and the nested +columns\code{product} and \code{company} holding the outputs at product and company +level. +} +\description{ +Add transition risk score and polish the output for delivery +} +\examples{ +library(readr, warn.conflicts = FALSE) +library(dplyr, warn.conflicts = FALSE) +library(tiltToyData, warn.conflicts = FALSE) +library(tiltIndicator) +library(tiltIndicatorAfter) + +set.seed(123) +restore <- options(list( + readr.show_col_types = FALSE, + tiltIndicatorAfter.output_co2_footprint = TRUE +)) + +toy_emissions_profile_products_ecoinvent <- read_csv(toy_emissions_profile_products_ecoinvent()) +toy_emissions_profile_any_companies <- read_csv(toy_emissions_profile_any_companies()) +toy_sector_profile_any_scenarios <- read_csv(toy_sector_profile_any_scenarios()) +toy_sector_profile_companies <- read_csv(toy_sector_profile_companies()) +toy_europages_companies <- read_csv(toy_europages_companies()) +toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) +toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) +toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) +toy_isic_name <- read_csv(toy_isic_name()) + +emissions_profile <- profile_emissions( + companies = toy_emissions_profile_any_companies, + co2 = toy_emissions_profile_products_ecoinvent, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name +) + +sector_profile <- profile_sector( + companies = toy_sector_profile_companies, + scenarios = toy_sector_profile_any_scenarios, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name +) + +result <- score_transition_risk_and_polish(emissions_profile, + sector_profile, + include_co2 = TRUE +) + +result |> unnest_product() + +result |> unnest_company() + +# Cleanup +options(restore) +} +\keyword{internal} diff --git a/man/tiltIndicatorAfter_options.Rd b/man/tiltIndicatorAfter_options.Rd new file mode 100644 index 0000000..66f63c9 --- /dev/null +++ b/man/tiltIndicatorAfter_options.Rd @@ -0,0 +1,59 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/tiltTransitionRisk-options.R +\name{tiltIndicatorAfter_options} +\alias{tiltIndicatorAfter_options} +\title{tiltTransitionRisk options} +\description{ +These options are meant to be used mainly by developers or analysts while +testing the code or creating data: +\itemize{ +\item \code{tiltIndicatorAfter.output_co2_footprint}: +\itemize{ +\item At product level it outputs licensed column \code{co2_footprint}. +\item At company level it outputs the column \code{co2_avg} (average \code{co2_footprint} +by \code{companies_id}). +} +\item \code{tiltIndicatorAfter.verbose}: Controls verbosity. +} +} +\examples{ +library(readr, warn.conflicts = FALSE) +library(dplyr, warn.conflicts = FALSE) +library(withr) +library(tiltToyData) +library(tiltIndicator) +library(tiltIndicatorAfter) + +set.seed(1) + +restore <- options(list( + readr.show_col_types = FALSE, + tiltIndicatorAfter.verbose = TRUE, + tiltIndicatorAfter.output_co2_footprint = TRUE +)) + +companies <- read_csv(toy_emissions_profile_any_companies()) +products <- read_csv(toy_emissions_profile_products_ecoinvent()) +europages_companies <- read_csv(toy_europages_companies()) +ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) +ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) +isic_name <- read_csv(toy_isic_name()) + +result <- profile_emissions( + companies, + products, + europages_companies = europages_companies, + ecoinvent_activities = ecoinvent_activities, + ecoinvent_europages = ecoinvent_europages, + isic = isic_name +) + +result |> + unnest_product() |> + select(matches(c("co2"))) + +result |> + unnest_company() |> + select(matches(c("co2"))) +} +\keyword{internal} diff --git a/man/tiltTransitionRisk-package.Rd b/man/tiltTransitionRisk-package.Rd index 45d055a..8472357 100644 --- a/man/tiltTransitionRisk-package.Rd +++ b/man/tiltTransitionRisk-package.Rd @@ -18,7 +18,19 @@ Useful links: } \author{ -\strong{Maintainer}: Mauro Lepore \email{maurolepore@gmail.com} (\href{https://orcid.org/0000-0002-1986-7988}{ORCID}) +\strong{Maintainer}: Kalash Singhal \email{kalash@2degrees-investing.org} + +Authors: +\itemize{ + \item Mauro Lepore \email{maurolepore@gmail.com} (\href{https://orcid.org/0000-0002-1986-7988}{ORCID}) + \item Anne Schoenauer \email{anne.schoenauer@2degrees-investing.org} (\href{https://orcid.org/0000-0002-4576-8799}{ORCID}) + \item Tilman Trompke \email{tilman@2degrees-investing.org} (\href{https://orcid.org/0009-0003-3351-5131}{ORCID}) +} + +Other contributors: +\itemize{ + \item 2 Degrees Investing Initiative \email{contact@2degrees-investing.org} [copyright holder, funder] +} } \keyword{internal} diff --git a/man/transition_risk_profile.Rd b/man/transition_risk_profile.Rd new file mode 100644 index 0000000..aad59f5 --- /dev/null +++ b/man/transition_risk_profile.Rd @@ -0,0 +1,99 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/transition_risk_profile.R +\name{transition_risk_profile} +\alias{transition_risk_profile} +\title{Calculate the indicator "transition risk profile"} +\usage{ +transition_risk_profile( + emissions_profile, + sector_profile, + co2, + all_activities_scenario_sectors, + scenarios, + for_webtool = FALSE +) +} +\arguments{ +\item{emissions_profile}{Nested data frame. The output of +\code{profile_emissions()}.} + +\item{sector_profile}{Nested data frame. The output of \code{profile_sector()}.} + +\item{co2}{A dataframe} + +\item{all_activities_scenario_sectors}{A dataframe} + +\item{scenarios}{A dataframe} + +\item{for_webtool}{Logical. Is it output for webtool or not?} +} +\value{ +A data frame with the column \code{companies_id}, and the nested +columns\code{product} and \code{company} holding the outputs at product and company +level. +} +\description{ +Adds the risk classification to calculated transition risk scores from +emission profile and sector profile indicator. +} +\examples{ +library(readr, warn.conflicts = FALSE) +library(dplyr, warn.conflicts = FALSE) +library(tiltToyData, warn.conflicts = FALSE) +library(tiltIndicator) +library(tiltIndicatorAfter) + +set.seed(123) +restore <- options(list( + readr.show_col_types = FALSE, + tiltIndicatorAfter.output_co2_footprint = TRUE +)) + +toy_emissions_profile_products_ecoinvent <- read_csv(toy_emissions_profile_products_ecoinvent()) +toy_emissions_profile_any_companies <- read_csv(toy_emissions_profile_any_companies()) +toy_sector_profile_any_scenarios <- read_csv(toy_sector_profile_any_scenarios()) +toy_sector_profile_companies <- read_csv(toy_sector_profile_companies()) +toy_europages_companies <- read_csv(toy_europages_companies()) +toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) +toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) +toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) +toy_isic_name <- read_csv(toy_isic_name()) +toy_all_activities_scenario_sectors <- read_csv(toy_all_activities_scenario_sectors()) + +toy_emissions_profile <- profile_emissions( + companies = toy_emissions_profile_any_companies, + co2 = toy_emissions_profile_products_ecoinvent, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name +) + +toy_sector_profile <- profile_sector( + companies = toy_sector_profile_companies, + scenarios = toy_sector_profile_any_scenarios, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name +) + +output <- transition_risk_profile( + emissions_profile = toy_emissions_profile, + sector_profile = toy_sector_profile, + co2 = toy_emissions_profile_products_ecoinvent, + all_activities_scenario_sectors = toy_all_activities_scenario_sectors, + scenarios = toy_sector_profile_any_scenarios, + for_webtool = FALSE +) + +output |> unnest_product() + +output |> unnest_company() +} +\seealso{ +Other top-level functions: +\code{\link{score_transition_risk}()} +} +\concept{profile functions} +\concept{top-level functions} diff --git a/tests/testthat/_snaps/exclude_cols_then_pivot_wider.md b/tests/testthat/_snaps/exclude_cols_then_pivot_wider.md new file mode 100644 index 0000000..504d67b --- /dev/null +++ b/tests/testthat/_snaps/exclude_cols_then_pivot_wider.md @@ -0,0 +1,4 @@ +# with `avoid_list_cols` AND `values_fn` errors gracefully + + `values_fn` should not be used when `avoid_list_cols = TRUE`. + diff --git a/tests/testthat/test-add_transition_risk_category.R b/tests/testthat/test-add_transition_risk_category_at_product_level.R similarity index 82% rename from tests/testthat/test-add_transition_risk_category.R rename to tests/testthat/test-add_transition_risk_category_at_product_level.R index 541c715..59f0694 100644 --- a/tests/testthat/test-add_transition_risk_category.R +++ b/tests/testthat/test-add_transition_risk_category_at_product_level.R @@ -11,15 +11,15 @@ test_that("if input data lacks crucial columns, errors gracefully", { crucial <- col_transition_risk_score() bad <- select(input_data, -all_of(crucial)) - expect_error(add_transition_risk_category(bad), crucial) + expect_error(add_transition_risk_category_at_product_level(bad), crucial) crucial <- col_tr_low_threshold() bad <- select(input_data, -all_of(crucial)) - expect_error(add_transition_risk_category(bad), crucial) + expect_error(add_transition_risk_category_at_product_level(bad), crucial) crucial <- col_tr_high_threshold() bad <- select(input_data, -all_of(crucial)) - expect_error(add_transition_risk_category(bad), crucial) + expect_error(add_transition_risk_category_at_product_level(bad), crucial) }) test_that("if `transition_risk_category` column has only NAs, then class of the column is `character`", { @@ -34,7 +34,7 @@ test_that("if `transition_risk_category` column has only NAs, then class of the all_activities_scenario_sectors, scenarios ) |> - add_transition_risk_category() + add_transition_risk_category_at_product_level() expected_class <- "character" expect_equal(class(output$transition_risk_category), expected_class) diff --git a/tests/testthat/test-avg_profile_ranking_best_case_worst_case.R b/tests/testthat/test-avg_profile_ranking_best_case_worst_case.R new file mode 100644 index 0000000..68a211b --- /dev/null +++ b/tests/testthat/test-avg_profile_ranking_best_case_worst_case.R @@ -0,0 +1,94 @@ +test_that("NA best case and worst case for a `benchmark` at produuct level gives NA to `avg_profile_ranking_best_case` and `avg_profile_ranking_worst_case` at company level", { + example_data_product <- example_best_case_worst_case_profile_ranking_product_level( + benchmark = c("all", "all", "unit"), + profile_ranking = c(1.0, 2.0, NA) + ) + + example_data_company <- example_best_case_worst_case_profile_ranking_company_level() + input <- tilt_profile(nest_levels(example_data_product, example_data_company)) + out <- input |> + best_case_worst_case_emission_profile() |> + best_case_worst_case_avg_profile_ranking() + + case_product <- out |> unnest_product() + case_company <- out |> unnest_company() + + case_product_benchmark <- filter(case_product, benchmark == "unit") + # `emissions_profile_best_case` is NA at product level for benchmark `unit` + expect_true(is.na(case_product_benchmark$emissions_profile_best_case)) + # `emissions_profile_worst_case` is NA at product level for benchmark `unit` + expect_true(is.na(case_product_benchmark$emissions_profile_worst_case)) + + case_company_benchmark <- filter(case_company, benchmark == "unit") + # `avg_profile_ranking_best_case` is NA at company level for benchmark `unit` + expect_true(is.na(case_company_benchmark$avg_profile_ranking_best_case)) + # `avg_profile_ranking_worst_case` is NA at company level for benchmark `unit` + expect_true(is.na(case_company_benchmark$avg_profile_ranking_worst_case)) +}) + +test_that("same best case and worst case for two products at produuct level gives only one row of that value to `avg_profile_ranking_best_case` and `avg_profile_ranking_worst_case` at company level", { + example_data_product <- example_best_case_worst_case_profile_ranking_product_level( + benchmark = c("all", "all", "unit"), + profile_ranking = c(1.0, 1.0, NA) + ) + + example_data_company <- example_best_case_worst_case_profile_ranking_company_level() + input <- tilt_profile(nest_levels(example_data_product, example_data_company)) + out <- input |> + best_case_worst_case_emission_profile() |> + best_case_worst_case_avg_profile_ranking() + + case_product <- out |> unnest_product() + case_company <- out |> unnest_company() + + # `emissions_profile_best_case` has same value for products `one` and `two` for benchmark `all` + case_product_benchmark <- distinct(filter(case_product, benchmark == "all")) + expected_same_value <- 1 + expect_equal(filter(case_product_benchmark, ep_product == "one")$emissions_profile_best_case, expected_same_value) + expect_equal(filter(case_product_benchmark, ep_product == "two")$emissions_profile_best_case, expected_same_value) + # `emissions_profile_worst_case` has same value for products `one` and `two` for benchmark `all` + expect_equal(filter(case_product_benchmark, ep_product == "one")$emissions_profile_worst_case, expected_same_value) + expect_equal(filter(case_product_benchmark, ep_product == "two")$emissions_profile_worst_case, expected_same_value) + + # `avg_profile_ranking_best_case` at company level is assigned one value for two similar `emissions_profile_best_case` of different products + expect_true(nrow(filter(case_company, benchmark == "all")) == 1) +}) + +test_that("if input to `best_case_worst_case_avg_profile_ranking` lacks crucial columns, errors gracefully", { + example_data_product <- example_best_case_worst_case_profile_ranking_product_level() + example_data_company <- example_best_case_worst_case_profile_ranking_company_level() + case_example_data_product <- tilt_profile(nest_levels(example_data_product, example_data_company)) |> + best_case_worst_case_emission_profile() |> + unnest_product() + + crucial <- col_companies_id() + bad <- select(example_data_product, -all_of(crucial)) + expect_error( + tilt_profile(nest_levels(bad, example_data_company)), + crucial + ) + + crucial <- col_emission_grouped_by() + bad <- select(case_example_data_product, -all_of(crucial)) + bad_product <- tilt_profile(nest_levels(bad, example_data_company)) + expect_error( + best_case_worst_case_avg_profile_ranking(bad_product), + crucial + ) + + crucial <- "emissions_profile_best_case" + bad <- select(case_example_data_product, -all_of(crucial)) + bad_product <- tilt_profile(nest_levels(bad, example_data_company)) + expect_error( + best_case_worst_case_avg_profile_ranking(bad_product), + crucial + ) + + crucial <- "emissions_profile_worst_case" + bad <- select(case_example_data_product, -all_of(crucial)) + bad_product <- tilt_profile(nest_levels(bad, example_data_company)) + expect_error( + best_case_worst_case_avg_profile_ranking(bad_product), + crucial + ) +}) diff --git a/tests/testthat/test-avg_transition_risk_best_case_worst_case.R b/tests/testthat/test-avg_transition_risk_best_case_worst_case.R new file mode 100644 index 0000000..f315de4 --- /dev/null +++ b/tests/testthat/test-avg_transition_risk_best_case_worst_case.R @@ -0,0 +1,97 @@ +test_that("NA best case and worst case for a `benchmark_tr_score` at produuct level gives NA to `avg_transition_risk_best_case` and `avg_transition_risk_worst_case` at company level", { + example_data_product <- example_best_case_worst_case_transition_risk_profile_product_level( + benchmark_tr_score = c("1.5C RPS_2030_all", "1.5C RPS_2030_all", "1.5C RPS_2050_all"), + transition_risk_score = c(1.0, 2.0, NA) + ) |> + best_case_worst_case_transition_risk_profile() |> + polish_best_case_worst_case() |> + polish_best_case_worst_case_transition_risk_profile() + + example_data_company <- example_best_case_worst_case_transition_risk_profile_company_level() + input <- tilt_profile(nest_levels(example_data_product, example_data_company)) + out <- best_case_worst_case_transition_risk_profile_at_company_level(input) + + case_product <- out |> unnest_product() + case_company <- out |> unnest_company() + + case_product_benchmark <- filter(case_product, benchmark_tr_score == "1.5C RPS_2050_all") + # `transition_risk_profile_best_case` is NA at product level for benchmark_tr_score `1.5C RPS_2050_all` + expect_true(is.na(case_product_benchmark$transition_risk_profile_best_case)) + # `transition_risk_profile_worst_case` is NA at product level for benchmark_tr_score `1.5C RPS_2050_all` + expect_true(is.na(case_product_benchmark$transition_risk_profile_worst_case)) + + case_company_benchmark <- filter(case_company, benchmark_tr_score_avg == "1.5C RPS_2050_all") + # `avg_transition_risk_best_case` is NA at company level for benchmark_tr_score `1.5C RPS_2050_all` + expect_true(is.na(case_company_benchmark$avg_transition_risk_best_case)) + # `avg_transition_risk_worst_case` is NA at company level for benchmark_tr_score `1.5C RPS_2050_all` + expect_true(is.na(case_company_benchmark$avg_transition_risk_worst_case)) +}) + +test_that("same best case and worst case for two products at produuct level gives only one row of that value to `avg_transition_risk_best_case` and `avg_transition_risk_worst_case` at company level", { + example_data_product <- example_best_case_worst_case_transition_risk_profile_product_level( + benchmark_tr_score = c("1.5C RPS_2030_all", "1.5C RPS_2030_all", "1.5C RPS_2050_all"), + transition_risk_score = c(1.0, 1.0, NA) + ) |> + best_case_worst_case_transition_risk_profile() |> + polish_best_case_worst_case() |> + polish_best_case_worst_case_transition_risk_profile() + + example_data_company <- example_best_case_worst_case_transition_risk_profile_company_level() + input <- tilt_profile(nest_levels(example_data_product, example_data_company)) + out <- best_case_worst_case_transition_risk_profile_at_company_level(input) + + case_product <- out |> unnest_product() + case_company <- out |> unnest_company() + + # `transition_risk_profile_best_case` has same value for products `one` and `two` for benchmark_tr_score `1.5C RPS_2030_all` + case_product_benchmark <- distinct(filter(case_product, benchmark_tr_score == "1.5C RPS_2030_all")) + expected_same_value <- 1 + expect_equal(filter(case_product_benchmark, ep_product == "one")$transition_risk_profile_best_case, expected_same_value) + expect_equal(filter(case_product_benchmark, ep_product == "two")$transition_risk_profile_best_case, expected_same_value) + # `transition_risk_profile_worst_case` has same value for products `one` and `two` for benchmark_tr_score `1.5C RPS_2030_all` + expect_equal(filter(case_product_benchmark, ep_product == "one")$transition_risk_profile_worst_case, expected_same_value) + expect_equal(filter(case_product_benchmark, ep_product == "two")$transition_risk_profile_worst_case, expected_same_value) + + # `avg_transition_risk_best_case` at company level is assigned one value for two similar `transition_risk_profile_best_case` of different products + expect_true(nrow(filter(case_company, benchmark_tr_score_avg == "1.5C RPS_2030_all")) == 1) +}) + +test_that("if input to `best_case_worst_case_transition_risk_profile_at_company_level` lacks crucial columns, errors gracefully", { + example_data_product <- example_best_case_worst_case_transition_risk_profile_product_level() |> + best_case_worst_case_transition_risk_profile() |> + polish_best_case_worst_case() |> + polish_best_case_worst_case_transition_risk_profile() + + example_data_company <- example_best_case_worst_case_transition_risk_profile_company_level() + + crucial <- col_companies_id() + bad <- select(example_data_product, -all_of(crucial)) + expect_error( + tilt_profile(nest_levels(bad, example_data_company)), + crucial + ) + + crucial <- col_transition_risk_grouped_by() + bad <- select(example_data_product, -all_of(crucial)) + bad_product <- tilt_profile(nest_levels(bad, example_data_company)) + expect_error( + best_case_worst_case_transition_risk_profile_at_company_level(bad_product), + crucial + ) + + crucial <- "transition_risk_profile_best_case" + bad <- select(example_data_product, -all_of(crucial)) + bad_product <- tilt_profile(nest_levels(bad, example_data_company)) + expect_error( + best_case_worst_case_transition_risk_profile_at_company_level(bad_product), + crucial + ) + + crucial <- "transition_risk_profile_worst_case" + bad <- select(example_data_product, -all_of(crucial)) + bad_product <- tilt_profile(nest_levels(bad, example_data_company)) + expect_error( + best_case_worst_case_transition_risk_profile_at_company_level(bad_product), + crucial + ) +}) diff --git a/tests/testthat/test-best_case_worst_case_avg_reduction_targets.R b/tests/testthat/test-best_case_worst_case_avg_reduction_targets.R new file mode 100644 index 0000000..3f69061 --- /dev/null +++ b/tests/testthat/test-best_case_worst_case_avg_reduction_targets.R @@ -0,0 +1,107 @@ +test_that("NA best case and worst case for a `scenario-year` at produuct level gives NA to `avg_reduction_targets_best_case` and `avg_reduction_targets_worst_case` at company level", { + example_data_product <- example_best_case_worst_case_reduction_targets_product_level( + scenario = c("1.5C RPS", "1.5C RPS", "1.5C RPS"), + year = c(2030, 2030, 2050), + reduction_targets = c(1.0, 2.0, NA) + ) + + example_data_company <- example_best_case_worst_case_reduction_targets_company_level() + input <- tilt_profile(nest_levels(example_data_product, example_data_company)) + out <- input |> + best_case_worst_case_sector_profile() |> + best_case_worst_case_avg_reduction_targets() + + case_product <- out |> unnest_product() + case_company <- out |> unnest_company() + + case_product_benchmark <- filter(case_product, scenario == "1.5C RPS", year == 2050) + # `sector_profile_best_case` is NA at product level for scenario `1.5C RPS` and year 2050 + expect_true(is.na(case_product_benchmark$sector_profile_best_case)) + # `sector_profile_worst_case` is NA at product level for scenario `1.5C RPS` and year 2050` + expect_true(is.na(case_product_benchmark$sector_profile_worst_case)) + + case_company_benchmark <- filter(case_company, scenario == "1.5C RPS", year == 2050) + # `avg_reduction_targets_best_case` is NA at company level for scenario `1.5C RPS` and year 2050 + expect_true(is.na(case_company_benchmark$avg_reduction_targets_best_case)) + # `avg_reduction_targets_worst_case` is NA at company level for scenario `1.5C RPS` and year 2050 + expect_true(is.na(case_company_benchmark$avg_reduction_targets_worst_case)) +}) + +test_that("same best case and worst case for two products at product level gives only one row of that value to `avg_reduction_targets_best_case` and `avg_reduction_targets_worst_case` at company level", { + example_data_product <- example_best_case_worst_case_reduction_targets_product_level( + scenario = c("1.5C RPS", "1.5C RPS", "1.5C RPS"), + year = c(2030, 2030, 2050), + reduction_targets = c(1.0, 1.0, NA) + ) + + example_data_company <- example_best_case_worst_case_reduction_targets_company_level() + input <- tilt_profile(nest_levels(example_data_product, example_data_company)) + out <- input |> + best_case_worst_case_sector_profile() |> + best_case_worst_case_avg_reduction_targets() + + case_product <- out |> unnest_product() + case_company <- out |> unnest_company() + + # `sector_profile_best_case` has same value for products `one` and `two` for scenario `1.5C RPS` and year 2030 + case_product_benchmark <- distinct(filter(case_product, scenario == "1.5C RPS", year == 2030)) + expected_same_value <- 1 + expect_equal(filter(case_product_benchmark, ep_product == "one")$sector_profile_best_case, expected_same_value) + expect_equal(filter(case_product_benchmark, ep_product == "two")$sector_profile_best_case, expected_same_value) + # `sector_profile_worst_case` has same value for products `one` and `two` for scenario `1.5C RPS` and year 2030 + expect_equal(filter(case_product_benchmark, ep_product == "one")$sector_profile_worst_case, expected_same_value) + expect_equal(filter(case_product_benchmark, ep_product == "two")$sector_profile_worst_case, expected_same_value) + + # `avg_reduction_targets_best_case` at company level is assigned one value for two similar `sector_profile_best_case` of different products + expect_true(nrow(filter(case_company, scenario == "1.5C RPS", year == 2030)) == 1) +}) + +test_that("if input to `best_case_worst_case_avg_profile_ranking` lacks crucial columns, errors gracefully", { + example_data_product <- example_best_case_worst_case_reduction_targets_product_level( + scenario = c("1.5C RPS", "1.5C RPS", "1.5C RPS"), + year = c(2030, 2030, 2050) + ) + example_data_company <- example_best_case_worst_case_reduction_targets_company_level() + case_example_data_product <- tilt_profile(nest_levels(example_data_product, example_data_company)) |> + best_case_worst_case_sector_profile() |> + unnest_product() + + crucial <- col_companies_id() + bad <- select(example_data_product, -all_of(crucial)) + expect_error( + tilt_profile(nest_levels(bad, example_data_company)), + crucial + ) + + crucial <- col_scenario() + bad <- select(case_example_data_product, -all_of(crucial)) + bad_product <- tilt_profile(nest_levels(bad, example_data_company)) + expect_error( + best_case_worst_case_avg_reduction_targets(bad_product), + crucial + ) + + crucial <- col_year() + bad <- select(case_example_data_product, -all_of(crucial)) + bad_product <- tilt_profile(nest_levels(bad, example_data_company)) + expect_error( + best_case_worst_case_avg_reduction_targets(bad_product), + crucial + ) + + crucial <- "sector_profile_best_case" + bad <- select(case_example_data_product, -all_of(crucial)) + bad_product <- tilt_profile(nest_levels(bad, example_data_company)) + expect_error( + best_case_worst_case_avg_reduction_targets(bad_product), + crucial + ) + + crucial <- "sector_profile_worst_case" + bad <- select(case_example_data_product, -all_of(crucial)) + bad_product <- tilt_profile(nest_levels(bad, example_data_company)) + expect_error( + best_case_worst_case_avg_reduction_targets(bad_product), + crucial + ) +}) diff --git a/tests/testthat/test-best_case_worst_case_transition_risk_profile.R b/tests/testthat/test-best_case_worst_case_transition_risk_profile.R new file mode 100644 index 0000000..78697c1 --- /dev/null +++ b/tests/testthat/test-best_case_worst_case_transition_risk_profile.R @@ -0,0 +1,138 @@ +test_that("Three `ep_products` with the same `benchmark_tr_score` but with different `transition_risk_score` will have `best_case` only for the lowest-scored product and have `worst_case` only for the highest-scored product", { + example_data <- example_best_case_worst_case_transition_risk_profile_product_level() + out <- best_case_worst_case_impl(example_data, + col_group_by = col_transition_risk_grouped_by(), + col_risk = col_transition_risk_category(), + col_rank = "transition_risk_score" + ) + + only_one_best_case <- 1 + expect_equal(nrow(filter(out, best_case == 1.0)), only_one_best_case) + + only_one_worst_case <- 1 + expect_equal(nrow(filter(out, worst_case == 3.0)), only_one_worst_case) + + # Expected best case for lowest-scored product + expected_best_case <- 1 + expect_equal(filter(out, transition_risk_score == 1.0)$best_case, expected_best_case) + + # Expected worst case for highest-scored product + expected_worst_case <- 3 + expect_equal(filter(out, transition_risk_score == 3.0)$worst_case, expected_worst_case) +}) + +test_that("`NA` in `transition_risk_score` for a single product gives `NA` in `best_case` and `worst_case` for that product", { + example_data <- example_best_case_worst_case_transition_risk_profile_product_level( + transition_risk_score = c(1.0, 2.0, NA_real_) + ) + out <- best_case_worst_case_impl(example_data, + col_group_by = col_transition_risk_grouped_by(), + col_risk = col_transition_risk_category(), + col_rank = "transition_risk_score" + ) + + # Expected best case for NA in `transition_risk_score` + expected_best_case <- NA_real_ + expect_equal(filter(out, is.na(transition_risk_score))$best_case, expected_best_case) + + # Expected worst case for NA in `transition_risk_score` + expected_worst_case <- NA_real_ + expect_equal(filter(out, is.na(transition_risk_score))$worst_case, expected_worst_case) +}) + +test_that("`NA` in `transition_risk_score` for all products gives `NA` in `best_case` and `worst_case` for all products", { + example_data <- example_best_case_worst_case_transition_risk_profile_product_level( + transition_risk_score = c(NA_real_, NA_real_, NA_real_) + ) + out <- best_case_worst_case_impl(example_data, + col_group_by = col_transition_risk_grouped_by(), + col_risk = col_transition_risk_category(), + col_rank = "transition_risk_score" + ) + + # Expected best case for NA in `transition_risk_score` + expected_best_case <- NA_real_ + expect_equal(unique(filter(out, is.na(transition_risk_score))$best_case), expected_best_case) + + # Expected worst case for NA in `transition_risk_score` + expected_worst_case <- NA_real_ + expect_equal(unique(filter(out, is.na(transition_risk_score))$worst_case), expected_worst_case) +}) + +test_that("gives `NA` in `equal_weight` if a company has missing `ep_product`", { + example_data <- example_best_case_worst_case_transition_risk_profile_product_level( + transition_risk_category = NA_character_, + ep_product = NA_character_ + ) + out <- best_case_worst_case_impl(example_data, + col_group_by = col_transition_risk_grouped_by(), + col_risk = col_transition_risk_category(), + col_rank = "transition_risk_score" + ) + + expect_true(all(is.na(out$equal_weight))) +}) + +test_that("if input to `best_case_worst_case_impl` lacks crucial columns, errors gracefully", { + example_data <- example_best_case_worst_case_transition_risk_profile_product_level() + + crucial <- col_companies_id() + bad <- select(example_data, -all_of(crucial)) + expect_error(best_case_worst_case_impl(bad, + col_group_by = col_transition_risk_grouped_by(), + col_risk = col_transition_risk_category(), + col_rank = "transition_risk_score" + ), crucial) + + crucial <- col_europages_product() + bad <- select(example_data, -all_of(crucial)) + expect_error(best_case_worst_case_impl(bad, + col_group_by = col_transition_risk_grouped_by(), + col_risk = col_transition_risk_category(), + col_rank = "transition_risk_score" + ), crucial) + + crucial <- col_transition_risk_grouped_by() + bad <- select(example_data, -all_of(crucial)) + expect_error(best_case_worst_case_impl(bad, + col_group_by = col_transition_risk_grouped_by(), + col_risk = col_transition_risk_category(), + col_rank = "transition_risk_score" + ), crucial) + + crucial <- col_transition_risk_category() + bad <- select(example_data, -all_of(crucial)) + expect_error(best_case_worst_case_impl(bad, + col_group_by = col_transition_risk_grouped_by(), + col_risk = col_transition_risk_category(), + col_rank = "transition_risk_score" + ), crucial) +}) + +test_that("`equal_weight` does not count unmatched `ep_product` after grouping by `companies_id` and `benchmark_tr_score`", { + example_data <- example_best_case_worst_case_transition_risk_profile_product_level( + companies_id = c("any", "any", "any", "any", "any"), + ep_product = c("one", "two", "three", "four", "five"), + benchmark_tr_score = c("1.5C RPS_2030_all", "1.5C RPS_2030_all", "1.5C RPS_2030_all", "1.5C RPS_2050_all", NA_character_), + transition_risk_category = c("low", "medium", NA_character_, "low", NA_character_), + transition_risk_score = c(1.0, 2.0, 3.0, 4.0, 5.0) + ) + + out <- best_case_worst_case_impl(example_data, + col_group_by = col_transition_risk_grouped_by(), + col_risk = col_transition_risk_category(), + col_rank = "transition_risk_score" + ) + + out_1.5C_RPS_2030_all <- filter(out, benchmark_tr_score == "1.5C RPS_2030_all") + expected_equal_weight_1.5C_RPS_2030_all <- 0.5 + expect_equal(unique(out_1.5C_RPS_2030_all$equal_weight), expected_equal_weight_1.5C_RPS_2030_all) + + out_1.5C_RPS_2050_all <- filter(out, benchmark_tr_score == "1.5C RPS_2050_all") + expected_equal_weight_1.5C_RPS_2050_all <- 1.0 + expect_equal(unique(out_1.5C_RPS_2050_all$equal_weight), expected_equal_weight_1.5C_RPS_2050_all) + + out_NA <- filter(out, is.na(benchmark_tr_score)) + expected_equal_weight_NA <- NA_real_ + expect_equal(unique(out_NA$equal_weight), expected_equal_weight_NA) +}) diff --git a/tests/testthat/test-coefficient_of_variation.R b/tests/testthat/test-coefficient_of_variation.R new file mode 100644 index 0000000..471dc1c --- /dev/null +++ b/tests/testthat/test-coefficient_of_variation.R @@ -0,0 +1,107 @@ +test_that("`add_coefficient_of_variation_transition_risk()` outputs correct `cov_transition_risk`", { + transition_risk_input <- tibble( + avg_transition_risk_equal_weight = c(1, 2, 5, NA_real_), + avg_transition_risk_best_case = c(1, 3, 7, NA_real_), + avg_transition_risk_worst_case = c(1, 4, 9, NA_real_) + ) + + out <- add_coefficient_of_variation_transition_risk(transition_risk_input) + + check_no_dispersion <- filter(out, avg_transition_risk_equal_weight == 1.0) + expected_coefficient_of_variation <- 0 + expect_true(check_no_dispersion$cov_transition_risk == + expected_coefficient_of_variation) + + check_na <- filter(out, is.na(avg_transition_risk_equal_weight)) + expect_true(is.na(check_na$cov_transition_risk)) +}) + +test_that("`add_coefficient_of_variation_emission_rank()` outputs correct `cov_emission_rank`", { + emission_rank_input <- tibble( + profile_ranking_avg = c(1, 2, 5, NA_real_), + avg_profile_ranking_best_case = c(1, 3, 7, NA_real_), + avg_profile_ranking_worst_case = c(1, 4, 9, NA_real_) + ) + + out <- add_coefficient_of_variation_emission_rank(emission_rank_input) + + check_no_dispersion <- filter(out, profile_ranking_avg == 1.0) + expected_coefficient_of_variation <- 0 + expect_true(check_no_dispersion$cov_emission_rank == + expected_coefficient_of_variation) + + check_na <- filter(out, is.na(profile_ranking_avg)) + expect_true(is.na(check_na$cov_emission_rank)) +}) + +test_that("`add_coefficient_of_variation_sector_target()` outputs correct `cov_sector_target`", { + sector_target_input <- tibble( + reduction_targets_avg = c(1, 2, 5, NA_real_), + avg_reduction_targets_best_case = c(1, 3, 7, NA_real_), + avg_reduction_targets_worst_case = c(1, 4, 9, NA_real_) + ) + + out <- add_coefficient_of_variation_sector_target(sector_target_input) + + check_no_dispersion <- filter(out, reduction_targets_avg == 1.0) + expected_coefficient_of_variation <- 0 + expect_true(check_no_dispersion$cov_sector_target == + expected_coefficient_of_variation) + + check_na <- filter(out, is.na(reduction_targets_avg)) + expect_true(is.na(check_na$cov_sector_target)) +}) + +test_that("`add_coefficient_of_variation_sector_target()` outputs NA `cov_sector_target` for zero mean", { + sector_target_input <- tibble( + reduction_targets_avg = -1, + avg_reduction_targets_best_case = 1, + avg_reduction_targets_worst_case = 0 + ) + out <- add_coefficient_of_variation_sector_target(sector_target_input) + + expect_true(is.na(out$cov_sector_target)) +}) + +test_that("`add_coefficient_of_variation_emission_rank()` outputs NA `cov_emission_rank` for zero mean", { + emission_rank_input <- tibble( + profile_ranking_avg = -1, + avg_profile_ranking_best_case = 1, + avg_profile_ranking_worst_case = 0 + ) + out <- add_coefficient_of_variation_emission_rank(emission_rank_input) + + expect_true(is.na(out$cov_emission_rank)) +}) + +test_that("`add_coefficient_of_variation_transition_risk()` outputs NA `cov_transition_risk` for zero mean", { + transition_risk_input <- tibble( + avg_transition_risk_equal_weight = -1, + avg_transition_risk_best_case = 1, + avg_transition_risk_worst_case = 0 + ) + out <- add_coefficient_of_variation_transition_risk(transition_risk_input) + + expect_true(is.na(out$cov_transition_risk)) +}) + +test_that("round off to 4 decimal places is required to give correct `cov_transition_risk`", { + transition_risk_input <- tibble( + avg_transition_risk_equal_weight = c(1.23456789, NA_real_), + avg_transition_risk_best_case = c(1.234567, NA_real_), + avg_transition_risk_worst_case = c(1.234567, NA_real_) + ) + + with_round_off <- round_off_to_4_decimal_places_impl(transition_risk_input) |> + add_coefficient_of_variation_transition_risk() + without_round_off <- add_coefficient_of_variation_transition_risk(transition_risk_input) + + zero_cov <- filter(with_round_off, !is.na(avg_transition_risk_equal_weight)) + non_zero_cov <- filter(without_round_off, !is.na(avg_transition_risk_equal_weight)) + + expected_coefficient_of_variation <- 0.0 + expect_true(zero_cov$cov_transition_risk == + expected_coefficient_of_variation) + expect_false(non_zero_cov$cov_transition_risk == + expected_coefficient_of_variation) +}) diff --git a/tests/testthat/test-create_risk_categories_at_company_level.R b/tests/testthat/test-create_risk_categories_at_company_level.R new file mode 100644 index 0000000..42b2491 --- /dev/null +++ b/tests/testthat/test-create_risk_categories_at_company_level.R @@ -0,0 +1,31 @@ +test_that("outputs expected columns at company level", { + example_data <- example_risk_categories_at_product_level() + out <- create_risk_categories_at_company_level(example_data) + + expected <- c( + "companies_id", "benchmark_tr_score_avg", + "transition_risk_category", "transition_risk_category_share" + ) + expect_equal(names(out)[seq_along(expected)], expected) +}) + +test_that("`transition_risk_category_share` sums up to 1 per `benchmark_tr_score_avg`", { + example_data <- example_risk_categories_at_product_level() + out <- create_risk_categories_at_company_level(example_data) + + sum <- unique(summarise(out, + sum = sum(transition_risk_category_share), + .by = benchmark_tr_score_avg + )$sum) + expect_equal(sum, 1) +}) + +test_that("outputs NA `transition_risk_category_share` for NA in `benchmark_tr_score` and `transition_risk_category`", { + example_data <- example_risk_categories_at_product_level( + benchmark_tr_score = NA_character_, + transition_risk_category = NA_character_ + ) + out <- create_risk_categories_at_company_level(example_data) + + expect_true(is.na(out$transition_risk_category_share)) +}) diff --git a/tests/testthat/test-exclude_cols_then_pivot_wider.R b/tests/testthat/test-exclude_cols_then_pivot_wider.R new file mode 100644 index 0000000..f49daf6 --- /dev/null +++ b/tests/testthat/test-exclude_cols_then_pivot_wider.R @@ -0,0 +1,60 @@ +test_that("excludes columns matching a pattern and leaves no duplicates", { + # styler: off + data <- tribble( + ~to_exclude, ~id, ~name, ~value, + 1, "id", "a", 1, + 2, "id", "a", 1, + 1, "id", "b", 2, + 2, "id", "b", 2, + ) + # styler: on + + out <- exclude_cols_then_pivot_wider(data, exclude_cols = "exclude") + expect_equal(nrow(out), 1L) + expect_false(hasName(out, "to_exclude")) +}) + +test_that("can avoid list-columns, the warning, and duplicates", { + # styler: off + data <- tribble( + ~to_exclude, ~id, ~name, ~value, + 1, "id", "a", 1, + 2, "id", "a", 1, + ) |> + mutate(another_col_that_yields_duplicates = to_exclude) + # styler: on + + + expect_no_warning({ + out <- exclude_cols_then_pivot_wider( + data, + exclude_cols = "to_exclude", + id_cols = "id", + avoid_list_cols = TRUE + ) + }) + + expect_type(out$a, "double") + expect_false(any(duplicated(out))) +}) + +test_that("with `avoid_list_cols` AND `values_fn` errors gracefully", { + # styler: off + data <- tribble( + ~to_exclude, ~id, ~name, ~value, + 1, "id", "a", 1, + 2, "id", "a", 1, + ) |> + mutate(another_col_that_yields_duplicates = to_exclude) + # styler: on + + expect_snapshot_error( + exclude_cols_then_pivot_wider( + data, + exclude_cols = "to_exclude", + id_cols = "id", + avoid_list_cols = TRUE, + values_fn = list + ) + ) +}) diff --git a/tests/testthat/test-score_transition_risk.R b/tests/testthat/test-score_transition_risk.R new file mode 100644 index 0000000..0f448bf --- /dev/null +++ b/tests/testthat/test-score_transition_risk.R @@ -0,0 +1,239 @@ +test_that("outputs expected columns at product level", { + emissions_profile_at_product_level <- + example_emissions_profile_at_product_level() |> + filter(companies_id == "antimonarchy_canine") + sector_profile_at_product_level <- + example_sector_profile_at_product_level() |> + filter(companies_id == "antimonarchy_canine") + + out <- + score_transition_risk( + emissions_profile_at_product_level, + sector_profile_at_product_level + ) |> + unnest_product() + + expect_equal(sort(names(out)), sort(trs_product_output_columns())) +}) + +test_that("outputs expected columns at company level", { + emissions_profile_at_product_level <- + example_emissions_profile_at_product_level() |> + filter(companies_id == "antimonarchy_canine") + sector_profile_at_product_level <- + example_sector_profile_at_product_level() |> + filter(companies_id == "antimonarchy_canine") + + out <- + score_transition_risk( + emissions_profile_at_product_level, + sector_profile_at_product_level + ) |> + unnest_company() + + expect_equal(sort(names(out)), sort(trs_company_output_columns())) +}) + +test_that("calculates `transition_risk_score` and `benchmark_tr_score` correctly", { + emissions_profile_at_product_level <- + example_emissions_profile_at_product_level() |> + filter( + companies_id %in% c("antimonarchy_canine"), + benchmark == "all" + ) + sector_profile_at_product_level <- + example_sector_profile_at_product_level() |> + filter( + companies_id %in% c("antimonarchy_canine"), + scenario == "1.5C RPS", + year == "2030" + ) + + out <- + unnest_product( + score_transition_risk( + emissions_profile_at_product_level, + sector_profile_at_product_level + ) + ) + + expect_equal(out$benchmark_tr_score, "1.5C RPS_2030_all") + expect_equal(out$transition_risk_score, 0.59) +}) + +test_that("calculates `transition_risk_score_avg` correctly", { + emissions_profile_at_product_level <- + example_emissions_profile_at_product_level() |> + filter( + companies_id %in% c("nonphilosophical_llama"), + benchmark == "all" + ) + sector_profile_at_product_level <- + example_sector_profile_at_product_level() |> + filter( + companies_id %in% c("nonphilosophical_llama"), + scenario == "1.5C RPS", + year == "2030" + ) + + out <- + unnest_company( + score_transition_risk( + emissions_profile_at_product_level, + sector_profile_at_product_level + ) + ) + + expect_equal(round(out$transition_risk_score_avg, 4), 0.2117) +}) + +test_that( + "calculates `transition_risk_score_avg` correctly for unmatched `ep_product` + of a company", + { + emissions_profile_at_product_level <- + example_emissions_profile_at_product_level() |> + filter( + companies_id %in% c("nonphilosophical_llama"), + ep_product == "surface finishing, galvanic" + ) + sector_profile_at_product_level <- + example_sector_profile_at_product_level() |> + filter( + companies_id %in% c("nonphilosophical_llama"), + ep_product == "surface engineering" + ) + + out <- + unnest_company( + score_transition_risk( + emissions_profile_at_product_level, + sector_profile_at_product_level + ) + ) + + # Both the ep_products are present only in one dataframe which will lead to + # unmatched results and thereafter Null in `transition_risk_score_avg` column + expect_equal(out$transition_risk_score_avg, NaN) + } +) + + +test_that( + "`transition_risk_score` and `benchmark_tr_score` has NA due to + NA in either column `profile_ranking` or `reduction_targets`", + { + emissions_profile_at_product_level <- + example_emissions_profile_at_product_level() |> + filter(companies_id %in% c("antimonarchy_canine", "nonphilosophical_llama")) + sector_profile_at_product_level <- + example_sector_profile_at_product_level() |> + filter(companies_id %in% c("celestial_lovebird", "nonphilosophical_llama")) + + out <- + score_transition_risk( + emissions_profile_at_product_level, + sector_profile_at_product_level + ) |> + unnest_product() + + tr_score_na <- out |> + filter(is.na(transition_risk_score)) + + benchmark_tr_score_na <- out |> + filter(is.na(benchmark_tr_score)) + + ranking_reduction_na <- out |> + filter(is.na(profile_ranking) | is.na(reduction_targets)) + + expect_equal(tr_score_na, ranking_reduction_na) + expect_equal(benchmark_tr_score_na, ranking_reduction_na) + } +) + +test_that( + "product level and company level outputs contain non-null info of all + matched and unmatched companies after joining dataframes", + { + # uncommon companies in either dataframe will give unmatched results + emissions_profile_at_product_level <- + example_emissions_profile_at_product_level() |> + filter(companies_id %in% c("antimonarchy_canine", "nonphilosophical_llama")) + sector_profile_at_product_level <- + example_sector_profile_at_product_level() |> + filter(companies_id %in% c("celestial_lovebird", "nonphilosophical_llama")) + + trs_product <- + score_transition_risk( + emissions_profile_at_product_level, + sector_profile_at_product_level + ) |> + unnest_product() + + trs_company <- + score_transition_risk( + emissions_profile_at_product_level, + sector_profile_at_product_level + ) |> + unnest_company() + + # Select common columns of both matched and unmatched companies (except columns + # computed by `score_transition_risk` function) + common_cols_product <- trs_product |> + select(common_columns_emissions_sector_at_product_level()) + common_cols_company <- trs_company |> + select(common_columns_emissions_sector_at_company_level()) + + # These checks ensures that there is not even a single NA in common columns + # of matched and unmatched companies at both product and company level + expect_false(any(is.na(common_cols_product))) + expect_false(any(is.na(common_cols_company))) + } +) + +test_that("characterize commit 663d12", { + emissions_profile_at_product_level <- + example_emissions_profile_at_product_level() |> + filter(companies_id == "antimonarchy_canine") + sector_profile_at_product_level <- + example_sector_profile_at_product_level() |> + filter(companies_id == "antimonarchy_canine") + + out <- + score_transition_risk( + emissions_profile_at_product_level, + sector_profile_at_product_level + ) + + out |> + unnest_product() |> + hasName("benchmark_tr_score") |> + expect_true() + + out |> + unnest_company() |> + hasName("benchmark_tr_score_avg") |> + expect_true() +}) + +test_that("limits `transition_risk_score` between 0 and 1", { + emissions_profile_at_product_level <- + example_emissions_profile_at_product_level() |> + filter(companies_id == "antimonarchy_canine") + sector_profile_at_product_level <- + example_sector_profile_at_product_level() |> + filter(companies_id == "antimonarchy_canine") |> + mutate(reduction_targets = c(-100, -100, 100, 100)) + + out <- + score_transition_risk( + emissions_profile_at_product_level, + sector_profile_at_product_level + ) |> + unnest_product() + + # Due to large positive and negative `reduction_targets` values, + # `transition_risk_score` should not be more than 1 and less than 0. + expected_values <- c(0, 1) + expect_equal(unique(out$transition_risk_score), expected_values) +}) diff --git a/tests/testthat/test-score_transition_risk_and_polish.R b/tests/testthat/test-score_transition_risk_and_polish.R new file mode 100644 index 0000000..29b1e92 --- /dev/null +++ b/tests/testthat/test-score_transition_risk_and_polish.R @@ -0,0 +1,112 @@ +test_that("outputs results both at product and company level", { + withr::local_options(list(tiltIndicatorAfter.output_co2_footprint = TRUE)) + + toy_emissions_profile_products_ecoinvent <- read_csv(toy_emissions_profile_products_ecoinvent()) + toy_emissions_profile_any_companies <- read_csv(toy_emissions_profile_any_companies()) + toy_sector_profile_any_scenarios <- read_csv(toy_sector_profile_any_scenarios()) + toy_sector_profile_companies <- read_csv(toy_sector_profile_companies()) + toy_europages_companies <- read_csv(toy_europages_companies()) + toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) + toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) + toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) + toy_isic_name <- read_csv(toy_isic_name()) + + emissions_profile <- profile_emissions( + companies = toy_emissions_profile_any_companies, + co2 = toy_emissions_profile_products_ecoinvent, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + + sector_profile <- profile_sector( + companies = toy_sector_profile_companies, + scenarios = toy_sector_profile_any_scenarios, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + + out <- score_transition_risk_and_polish(emissions_profile, sector_profile) + expect_named(out, c("companies_id", "product", "company")) +}) + +test_that("with `*.output_co2_footprint` unset, `include_co2 = TRUE` yields an error", { + unset <- NULL + withr::local_options(list(tiltIndicatorAfter.output_co2_footprint = unset)) + + toy_emissions_profile_products_ecoinvent <- read_csv(toy_emissions_profile_products_ecoinvent()) + toy_emissions_profile_any_companies <- read_csv(toy_emissions_profile_any_companies()) + toy_sector_profile_any_scenarios <- read_csv(toy_sector_profile_any_scenarios()) + toy_sector_profile_companies <- read_csv(toy_sector_profile_companies()) + toy_europages_companies <- read_csv(toy_europages_companies()) + toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) + toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) + toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) + toy_isic_name <- read_csv(toy_isic_name()) + + emissions_profile <- profile_emissions( + companies = toy_emissions_profile_any_companies, + co2 = toy_emissions_profile_products_ecoinvent, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + + sector_profile <- profile_sector( + companies = toy_sector_profile_companies, + scenarios = toy_sector_profile_any_scenarios, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + + expect_error( + score_transition_risk_and_polish(emissions_profile, sector_profile, include_co2 = TRUE), + "tiltIndicatorAfter.output_co2_footprint" + ) +}) + +test_that("with `*.output_co2_footprint` unset, `include_co2 = FALSE` yields no error", { + unset <- NULL + withr::local_options(list(tiltIndicatorAfter.output_co2_footprint = unset)) + + toy_emissions_profile_products_ecoinvent <- read_csv(toy_emissions_profile_products_ecoinvent()) + toy_emissions_profile_any_companies <- read_csv(toy_emissions_profile_any_companies()) + toy_sector_profile_any_scenarios <- read_csv(toy_sector_profile_any_scenarios()) + toy_sector_profile_companies <- read_csv(toy_sector_profile_companies()) + toy_europages_companies <- read_csv(toy_europages_companies()) + toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) + toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) + toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) + toy_isic_name <- read_csv(toy_isic_name()) + + emissions_profile <- profile_emissions( + companies = toy_emissions_profile_any_companies, + co2 = toy_emissions_profile_products_ecoinvent, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + + sector_profile <- profile_sector( + companies = toy_sector_profile_companies, + scenarios = toy_sector_profile_any_scenarios, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + + expect_no_error( + score_transition_risk_and_polish( + emissions_profile, + sector_profile + ) + ) +}) diff --git a/tests/testthat/test-transition_risk_profile.R b/tests/testthat/test-transition_risk_profile.R new file mode 100644 index 0000000..851cb89 --- /dev/null +++ b/tests/testthat/test-transition_risk_profile.R @@ -0,0 +1,746 @@ +test_that("yields a 'tilt_profile'", { + restore <- options(list(tiltIndicatorAfter.output_co2_footprint = TRUE)) + toy_emissions_profile_products_ecoinvent <- read_csv(toy_emissions_profile_products_ecoinvent()) |> + filter(activity_uuid_product_uuid != "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_emissions_profile_any_companies <- read_csv(toy_emissions_profile_any_companies()) + toy_sector_profile_any_scenarios <- read_csv(toy_sector_profile_any_scenarios()) + toy_sector_profile_companies <- read_csv(toy_sector_profile_companies()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_europages_companies <- read_csv(toy_europages_companies()) + toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) + toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) + toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) + toy_isic_name <- read_csv(toy_isic_name()) + toy_all_activities_scenario_sectors <- read_csv(toy_all_activities_scenario_sectors()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + + toy_emissions_profile <- profile_emissions( + companies = toy_emissions_profile_any_companies, + co2 = toy_emissions_profile_products_ecoinvent, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + toy_sector_profile <- profile_sector( + companies = toy_sector_profile_companies, + scenarios = toy_sector_profile_any_scenarios, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + + output <- transition_risk_profile( + emissions_profile = toy_emissions_profile, + sector_profile = toy_sector_profile, + co2 = toy_emissions_profile_products_ecoinvent, + all_activities_scenario_sectors = toy_all_activities_scenario_sectors, + scenarios = toy_sector_profile_any_scenarios + ) + + expect_s3_class(output, "tilt_profile") +}) + + +test_that("outputs `NA` transition risk category for `NA` transition risk score at product level", { + restore <- options(list(tiltIndicatorAfter.output_co2_footprint = TRUE)) + toy_emissions_profile_products_ecoinvent <- read_csv(toy_emissions_profile_products_ecoinvent()) |> + filter(activity_uuid_product_uuid != "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_emissions_profile_any_companies <- read_csv(toy_emissions_profile_any_companies()) + toy_sector_profile_any_scenarios <- read_csv(toy_sector_profile_any_scenarios()) + toy_sector_profile_companies <- read_csv(toy_sector_profile_companies()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_europages_companies <- read_csv(toy_europages_companies()) + toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) + toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) + toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) + toy_isic_name <- read_csv(toy_isic_name()) + toy_all_activities_scenario_sectors <- read_csv(toy_all_activities_scenario_sectors()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + + toy_emissions_profile <- profile_emissions( + companies = toy_emissions_profile_any_companies, + co2 = toy_emissions_profile_products_ecoinvent, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + toy_sector_profile <- profile_sector( + companies = toy_sector_profile_companies, + scenarios = toy_sector_profile_any_scenarios, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + + output <- transition_risk_profile( + emissions_profile = toy_emissions_profile, + sector_profile = toy_sector_profile, + co2 = toy_emissions_profile_products_ecoinvent, + all_activities_scenario_sectors = toy_all_activities_scenario_sectors, + scenarios = toy_sector_profile_any_scenarios + ) |> + unnest_product() |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + + # Transition risk score is `NA` for uuid "76269c17-78d6-420b-991a-aa38c51b45b7" + expect_true(is.na(unique(output$transition_risk_score))) + # `transition_risk_category` is `NA` for `NA` transition risk score + expect_true(is.na(unique(output$transition_risk_category))) +}) + +test_that("outputs `NA` in `avg_transition_risk_best_case` and `avg_transition_risk_worst_case` for `NA` at company level if `transition_risk_score` and `transition_risk_category` are `NA` at product level", { + restore <- options(list(tiltIndicatorAfter.output_co2_footprint = TRUE)) + toy_emissions_profile_products_ecoinvent <- read_csv(toy_emissions_profile_products_ecoinvent()) |> + filter(activity_uuid_product_uuid != "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_emissions_profile_any_companies <- read_csv(toy_emissions_profile_any_companies()) + toy_sector_profile_any_scenarios <- read_csv(toy_sector_profile_any_scenarios()) + toy_sector_profile_companies <- read_csv(toy_sector_profile_companies()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_europages_companies <- read_csv(toy_europages_companies()) + toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) + toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) + toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) + toy_isic_name <- read_csv(toy_isic_name()) + toy_all_activities_scenario_sectors <- read_csv(toy_all_activities_scenario_sectors()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + + toy_emissions_profile <- profile_emissions( + companies = toy_emissions_profile_any_companies, + co2 = toy_emissions_profile_products_ecoinvent, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + toy_sector_profile <- profile_sector( + companies = toy_sector_profile_companies, + scenarios = toy_sector_profile_any_scenarios, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + + output <- transition_risk_profile( + emissions_profile = toy_emissions_profile, + sector_profile = toy_sector_profile, + co2 = toy_emissions_profile_products_ecoinvent, + all_activities_scenario_sectors = toy_all_activities_scenario_sectors, + scenarios = toy_sector_profile_any_scenarios + ) + + product_level_output <- output |> + unnest_product() + + company_level_output <- output |> + unnest_company() + + # `avg_transition_risk_equal_weight` and `transition_risk_category` are `NA`at product level + expect_true(is.na(unique(product_level_output$transition_risk_score))) + expect_true(is.na(unique(product_level_output$transition_risk_category))) + # `avg_transition_risk_best_case` and `avg_transition_risk_worst_case` are `NA` are `NA` at company level + expect_true(is.na(unique(company_level_output$avg_transition_risk_best_case))) + expect_true(is.na(unique(company_level_output$avg_transition_risk_worst_case))) +}) + +test_that("with `*.output_co2_footprint` unset, `for_webtool = TRUE` yields no error", { + unset <- NULL + withr::local_options(list(tiltIndicatorAfter.output_co2_footprint = unset)) + + toy_emissions_profile_products_ecoinvent <- read_csv(toy_emissions_profile_products_ecoinvent()) |> + filter(activity_uuid_product_uuid != "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_emissions_profile_any_companies <- read_csv(toy_emissions_profile_any_companies()) + toy_sector_profile_any_scenarios <- read_csv(toy_sector_profile_any_scenarios()) + toy_sector_profile_companies <- read_csv(toy_sector_profile_companies()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_europages_companies <- read_csv(toy_europages_companies()) + toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) + toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) + toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) + toy_isic_name <- read_csv(toy_isic_name()) + toy_all_activities_scenario_sectors <- read_csv(toy_all_activities_scenario_sectors()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + + toy_emissions_profile <- profile_emissions( + companies = toy_emissions_profile_any_companies, + co2 = toy_emissions_profile_products_ecoinvent, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + toy_sector_profile <- profile_sector( + companies = toy_sector_profile_companies, + scenarios = toy_sector_profile_any_scenarios, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + + expect_no_error( + transition_risk_profile( + emissions_profile = toy_emissions_profile, + sector_profile = toy_sector_profile, + co2 = toy_emissions_profile_products_ecoinvent, + all_activities_scenario_sectors = toy_all_activities_scenario_sectors, + scenarios = toy_sector_profile_any_scenarios, + for_webtool = TRUE + ) + ) +}) + +test_that("doesn't output `co2_footprint` at product level and `co2e_avg` at company level if `*.output_co2_footprint` unset and `for_webtool = TRUE`", { + unset <- NULL + withr::local_options(list(tiltIndicatorAfter.output_co2_footprint = unset)) + + toy_emissions_profile_products_ecoinvent <- read_csv(toy_emissions_profile_products_ecoinvent()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_emissions_profile_any_companies <- read_csv(toy_emissions_profile_any_companies()) + toy_sector_profile_any_scenarios <- read_csv(toy_sector_profile_any_scenarios()) + toy_sector_profile_companies <- read_csv(toy_sector_profile_companies()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_europages_companies <- read_csv(toy_europages_companies()) + toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) + toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) + toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) + toy_isic_name <- read_csv(toy_isic_name()) + toy_all_activities_scenario_sectors <- read_csv(toy_all_activities_scenario_sectors()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + + toy_emissions_profile <- profile_emissions( + companies = toy_emissions_profile_any_companies, + co2 = toy_emissions_profile_products_ecoinvent, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + toy_sector_profile <- profile_sector( + companies = toy_sector_profile_companies, + scenarios = toy_sector_profile_any_scenarios, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + + output <- transition_risk_profile( + emissions_profile = toy_emissions_profile, + sector_profile = toy_sector_profile, + co2 = toy_emissions_profile_products_ecoinvent, + all_activities_scenario_sectors = toy_all_activities_scenario_sectors, + scenarios = toy_sector_profile_any_scenarios, + for_webtool = TRUE + ) + + expect_false("co2_footprint" %in% names(unnest_product(output))) + expect_false("co2e_avg" %in% names(unnest_company(output))) +}) + + +test_that("outputs `co2_footprint` at product level and `co2e_avg` at company level if `*.output_co2_footprint = TRUE` and `for_webtool = FALSE`", { + withr::local_options(list(tiltIndicatorAfter.output_co2_footprint = TRUE)) + + toy_emissions_profile_products_ecoinvent <- read_csv(toy_emissions_profile_products_ecoinvent()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_emissions_profile_any_companies <- read_csv(toy_emissions_profile_any_companies()) + toy_sector_profile_any_scenarios <- read_csv(toy_sector_profile_any_scenarios()) + toy_sector_profile_companies <- read_csv(toy_sector_profile_companies()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_europages_companies <- read_csv(toy_europages_companies()) + toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) + toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) + toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) + toy_isic_name <- read_csv(toy_isic_name()) + toy_all_activities_scenario_sectors <- read_csv(toy_all_activities_scenario_sectors()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + + toy_emissions_profile <- profile_emissions( + companies = toy_emissions_profile_any_companies, + co2 = toy_emissions_profile_products_ecoinvent, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + toy_sector_profile <- profile_sector( + companies = toy_sector_profile_companies, + scenarios = toy_sector_profile_any_scenarios, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + + output <- transition_risk_profile( + emissions_profile = toy_emissions_profile, + sector_profile = toy_sector_profile, + co2 = toy_emissions_profile_products_ecoinvent, + all_activities_scenario_sectors = toy_all_activities_scenario_sectors, + scenarios = toy_sector_profile_any_scenarios + ) + + expect_true("co2_footprint" %in% names(unnest_product(output))) + expect_true("co2e_avg" %in% names(unnest_company(output))) +}) + +test_that("removes `co2_footprint` at product level and `co2e_avg` at company level if `*.output_co2_footprint = TRUE` and `for_webtool = TRUE`", { + withr::local_options(list(tiltIndicatorAfter.output_co2_footprint = TRUE)) + + toy_emissions_profile_products_ecoinvent <- read_csv(toy_emissions_profile_products_ecoinvent()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_emissions_profile_any_companies <- read_csv(toy_emissions_profile_any_companies()) + toy_sector_profile_any_scenarios <- read_csv(toy_sector_profile_any_scenarios()) + toy_sector_profile_companies <- read_csv(toy_sector_profile_companies()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_europages_companies <- read_csv(toy_europages_companies()) + toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) + toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) + toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) + toy_isic_name <- read_csv(toy_isic_name()) + toy_all_activities_scenario_sectors <- read_csv(toy_all_activities_scenario_sectors()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + + toy_emissions_profile <- profile_emissions( + companies = toy_emissions_profile_any_companies, + co2 = toy_emissions_profile_products_ecoinvent, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + toy_sector_profile <- profile_sector( + companies = toy_sector_profile_companies, + scenarios = toy_sector_profile_any_scenarios, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + + output <- transition_risk_profile( + emissions_profile = toy_emissions_profile, + sector_profile = toy_sector_profile, + co2 = toy_emissions_profile_products_ecoinvent, + all_activities_scenario_sectors = toy_all_activities_scenario_sectors, + scenarios = toy_sector_profile_any_scenarios, + for_webtool = TRUE + ) + + expect_true(!("co2_footprint" %in% names(unnest_product(output)))) + expect_true(!("co2e_avg" %in% names(unnest_company(output)))) +}) + + +test_that("At company level the `emission*` column are of type double", { + withr::local_options(list(tiltIndicatorAfter.output_co2_footprint = TRUE)) + + toy_emissions_profile_products_ecoinvent <- read_csv(toy_emissions_profile_products_ecoinvent()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_emissions_profile_any_companies <- read_csv(toy_emissions_profile_any_companies()) + toy_sector_profile_any_scenarios <- read_csv(toy_sector_profile_any_scenarios()) + toy_sector_profile_companies <- read_csv(toy_sector_profile_companies()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_europages_companies <- read_csv(toy_europages_companies()) + toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) + toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) + toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) + toy_isic_name <- read_csv(toy_isic_name()) + toy_all_activities_scenario_sectors <- read_csv(toy_all_activities_scenario_sectors()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + + toy_emissions_profile <- profile_emissions( + companies = toy_emissions_profile_any_companies, + co2 = toy_emissions_profile_products_ecoinvent, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + toy_sector_profile <- profile_sector( + companies = toy_sector_profile_companies, + scenarios = toy_sector_profile_any_scenarios, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + + type <- transition_risk_profile( + emissions_profile = toy_emissions_profile, + sector_profile = toy_sector_profile, + co2 = toy_emissions_profile_products_ecoinvent, + all_activities_scenario_sectors = toy_all_activities_scenario_sectors, + scenarios = toy_sector_profile_any_scenarios + ) |> + unnest_company() |> + select(matches("emission_")) |> + lapply(typeof) |> + unlist() |> + unique() + expect_equal(type, "double") +}) + +test_that("the output at product level has all the new required columns (#189)", { + toy_emissions_profile_products_ecoinvent <- read_csv(toy_emissions_profile_products_ecoinvent()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_emissions_profile_any_companies <- read_csv(toy_emissions_profile_any_companies()) + toy_sector_profile_any_scenarios <- read_csv(toy_sector_profile_any_scenarios()) + toy_sector_profile_companies <- read_csv(toy_sector_profile_companies()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_europages_companies <- read_csv(toy_europages_companies()) + toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) + toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) + toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) + toy_isic_name <- read_csv(toy_isic_name()) + toy_all_activities_scenario_sectors <- read_csv(toy_all_activities_scenario_sectors()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + + toy_emissions_profile <- profile_emissions( + companies = toy_emissions_profile_any_companies, + co2 = toy_emissions_profile_products_ecoinvent, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + toy_sector_profile <- profile_sector( + companies = toy_sector_profile_companies, + scenarios = toy_sector_profile_any_scenarios, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + + product <- transition_risk_profile( + emissions_profile = toy_emissions_profile, + sector_profile = toy_sector_profile, + co2 = toy_emissions_profile_products_ecoinvent, + all_activities_scenario_sectors = toy_all_activities_scenario_sectors, + scenarios = toy_sector_profile_any_scenarios + ) |> + unnest_product() + + expect_true(any(matches_name(product, "postcode"))) + expect_true(any(matches_name(product, "address"))) + expect_true(any(matches_name(product, "min_headcount"))) + expect_true(any(matches_name(product, "max_headcount"))) + expect_true(any(matches_name(product, "emissions_profile_best_case"))) + expect_true(any(matches_name(product, "emissions_profile_worst_case"))) + expect_true(any(matches_name(product, "transition_risk_profile_best_case"))) + expect_true(any(matches_name(product, "transition_risk_profile_worst_case"))) + expect_true(any(matches_name(product, "isic_4digit"))) + expect_true(any(matches_name(product, "matching_certainty"))) + expect_true(any(matches_name(product, "company_name"))) + expect_true(any(matches_name(product, "emissions_profile_equal_weight"))) + expect_true(any(matches_name(product, "amount_of_distinct_products_matched"))) +}) + +test_that("the output at company level has has all the new required columns (#189, #290)", { + toy_emissions_profile_products_ecoinvent <- read_csv(toy_emissions_profile_products_ecoinvent()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_emissions_profile_any_companies <- read_csv(toy_emissions_profile_any_companies()) + toy_sector_profile_any_scenarios <- read_csv(toy_sector_profile_any_scenarios()) + toy_sector_profile_companies <- read_csv(toy_sector_profile_companies()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_europages_companies <- read_csv(toy_europages_companies()) + toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) + toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) + toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) + toy_isic_name <- read_csv(toy_isic_name()) + toy_all_activities_scenario_sectors <- read_csv(toy_all_activities_scenario_sectors()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + + toy_emissions_profile <- profile_emissions( + companies = toy_emissions_profile_any_companies, + co2 = toy_emissions_profile_products_ecoinvent, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + toy_sector_profile <- profile_sector( + companies = toy_sector_profile_companies, + scenarios = toy_sector_profile_any_scenarios, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + + company <- transition_risk_profile( + emissions_profile = toy_emissions_profile, + sector_profile = toy_sector_profile, + co2 = toy_emissions_profile_products_ecoinvent, + all_activities_scenario_sectors = toy_all_activities_scenario_sectors, + scenarios = toy_sector_profile_any_scenarios + ) |> + unnest_company() + + expect_true(any(matches_name(company, "postcode"))) + expect_true(any(matches_name(company, "address"))) + expect_true(any(matches_name(company, "min_headcount"))) + expect_true(any(matches_name(company, "max_headcount"))) + expect_true(any(matches_name(company, "company"))) + expect_true(any(matches_name(company, "emission_rank_avg_best_case"))) + expect_true(any(matches_name(company, "emission_rank_avg_worst_case"))) + expect_true(any(matches_name(company, "sector_target_avg_best_case"))) + expect_true(any(matches_name(company, "sector_target_avg_worst_case"))) + expect_true(any(matches_name(company, "cov_transition_risk"))) + expect_true(any(matches_name(company, "cov_emission_rank"))) + expect_true(any(matches_name(company, "cov_sector_target"))) +}) + +test_that("At product level, when either `sector_category` is NA or `emission_category` is NA, tilt and isic sectors are not NA", { + toy_emissions_profile_products_ecoinvent <- read_csv(toy_emissions_profile_products_ecoinvent()) |> + filter(activity_uuid_product_uuid != "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_emissions_profile_any_companies <- read_csv(toy_emissions_profile_any_companies()) + toy_sector_profile_any_scenarios <- read_csv(toy_sector_profile_any_scenarios()) + toy_sector_profile_companies <- read_csv(toy_sector_profile_companies()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_europages_companies <- read_csv(toy_europages_companies()) + toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) + toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) + toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) + toy_isic_name <- read_csv(toy_isic_name()) + toy_all_activities_scenario_sectors <- read_csv(toy_all_activities_scenario_sectors()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + + toy_emissions_profile <- profile_emissions( + companies = toy_emissions_profile_any_companies, + co2 = toy_emissions_profile_products_ecoinvent, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + toy_sector_profile <- profile_sector( + companies = toy_sector_profile_companies, + scenarios = toy_sector_profile_any_scenarios, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + + output_product <- transition_risk_profile( + emissions_profile = toy_emissions_profile, + sector_profile = toy_sector_profile, + co2 = toy_emissions_profile_products_ecoinvent, + all_activities_scenario_sectors = toy_all_activities_scenario_sectors, + scenarios = toy_sector_profile_any_scenarios + ) |> unnest_product() + + # when `sector_category` is NA then, tilt and isic sectors are not NA + out_sector_na <- filter(output_product, is.na(sector_category)) + expect_true(nrow(filter(out_sector_na, is.na(out_sector_na$tilt_sector))) == 0) + expect_true(nrow(filter(out_sector_na, is.na(out_sector_na$tilt_subsector))) == 0) + expect_true(nrow(filter(out_sector_na, is.na(out_sector_na$isic_4digit))) == 0) + + # when `emission_category` is NA then, tilt and isic sectors are not NA + out_emissions_na <- filter(output_product, is.na(emission_category)) + expect_true(nrow(filter(out_emissions_na, is.na(out_emissions_na$tilt_sector))) == 0) + expect_true(nrow(filter(out_emissions_na, is.na(out_emissions_na$tilt_subsector))) == 0) + expect_true(nrow(filter(out_emissions_na, is.na(out_emissions_na$isic_4digit))) == 0) +}) + +test_that("`transition_risk_NA_share` is not NA for all cases of benchmark combinations", { + toy_emissions_profile_products_ecoinvent <- read_csv(toy_emissions_profile_products_ecoinvent()) |> + filter(activity_uuid_product_uuid != "833caa78-30df-4374-900f-7f88ab44075b") + toy_emissions_profile_any_companies <- read_csv(toy_emissions_profile_any_companies()) + toy_sector_profile_any_scenarios <- read_csv(toy_sector_profile_any_scenarios()) + toy_sector_profile_companies <- read_csv(toy_sector_profile_companies()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_europages_companies <- read_csv(toy_europages_companies()) + toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) + toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) + toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) + toy_isic_name <- read_csv(toy_isic_name()) + toy_all_activities_scenario_sectors <- read_csv(toy_all_activities_scenario_sectors()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + + toy_emissions_profile <- profile_emissions( + companies = toy_emissions_profile_any_companies, + co2 = toy_emissions_profile_products_ecoinvent, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + toy_sector_profile <- profile_sector( + companies = toy_sector_profile_companies, + scenarios = toy_sector_profile_any_scenarios, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + + output <- transition_risk_profile( + emissions_profile = toy_emissions_profile, + sector_profile = toy_sector_profile, + co2 = toy_emissions_profile_products_ecoinvent, + all_activities_scenario_sectors = toy_all_activities_scenario_sectors, + scenarios = toy_sector_profile_any_scenarios + ) + + output_product <- output |> unnest_product() + benchmark_cases <- c("1.5C RPS_2030_all", "NA_NA_all", "NA_NA_NA") + expect_true(all(benchmark_cases %in% unique(output_product$grouping_transition_risk))) + + out_na <- filter(output_product, is.na(transition_risk_NA_share)) + expect_true(nrow(out_na) == 0) +}) + +test_that("`transition_risk_NA_share` is not greater than 1 and not less than 0 for all cases of benchmark combinations", { + toy_emissions_profile_products_ecoinvent <- read_csv(toy_emissions_profile_products_ecoinvent()) |> + filter(activity_uuid_product_uuid != "833caa78-30df-4374-900f-7f88ab44075b") + toy_emissions_profile_any_companies <- read_csv(toy_emissions_profile_any_companies()) + toy_sector_profile_any_scenarios <- read_csv(toy_sector_profile_any_scenarios()) + toy_sector_profile_companies <- read_csv(toy_sector_profile_companies()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_europages_companies <- read_csv(toy_europages_companies()) + toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) + toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) + toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) + toy_isic_name <- read_csv(toy_isic_name()) + toy_all_activities_scenario_sectors <- read_csv(toy_all_activities_scenario_sectors()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + + toy_emissions_profile <- profile_emissions( + companies = toy_emissions_profile_any_companies, + co2 = toy_emissions_profile_products_ecoinvent, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + toy_sector_profile <- profile_sector( + companies = toy_sector_profile_companies, + scenarios = toy_sector_profile_any_scenarios, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + + output <- transition_risk_profile( + emissions_profile = toy_emissions_profile, + sector_profile = toy_sector_profile, + co2 = toy_emissions_profile_products_ecoinvent, + all_activities_scenario_sectors = toy_all_activities_scenario_sectors, + scenarios = toy_sector_profile_any_scenarios + ) + + output_product <- output |> unnest_product() + benchmark_cases <- c("1.5C RPS_2030_all", "NA_NA_all", "NA_NA_NA") + expect_true(all(benchmark_cases %in% unique(output_product$grouping_transition_risk))) + + out_na <- unique(output_product$transition_risk_NA_share) + expect_false(all(out_na < 0)) + expect_false(all(out_na > 1)) +}) + +test_that("is sensitive to `for_webtool`", { + withr::local_options(list(tiltIndicatorAfter.output_co2_footprint = TRUE)) + + toy_emissions_profile_products_ecoinvent <- read_csv(toy_emissions_profile_products_ecoinvent()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_emissions_profile_any_companies <- read_csv(toy_emissions_profile_any_companies()) + toy_sector_profile_any_scenarios <- read_csv(toy_sector_profile_any_scenarios()) + toy_sector_profile_companies <- read_csv(toy_sector_profile_companies()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + toy_europages_companies <- read_csv(toy_europages_companies()) + toy_ecoinvent_activities <- read_csv(toy_ecoinvent_activities()) + toy_ecoinvent_europages <- read_csv(toy_ecoinvent_europages()) + toy_ecoinvent_inputs <- read_csv(toy_ecoinvent_inputs()) + toy_isic_name <- read_csv(toy_isic_name()) + toy_all_activities_scenario_sectors <- read_csv(toy_all_activities_scenario_sectors()) |> + filter(activity_uuid_product_uuid == "76269c17-78d6-420b-991a-aa38c51b45b7") + + toy_emissions_profile <- profile_emissions( + companies = toy_emissions_profile_any_companies, + co2 = toy_emissions_profile_products_ecoinvent, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + toy_sector_profile <- profile_sector( + companies = toy_sector_profile_companies, + scenarios = toy_sector_profile_any_scenarios, + europages_companies = toy_europages_companies, + ecoinvent_activities = toy_ecoinvent_activities, + ecoinvent_europages = toy_ecoinvent_europages, + isic = toy_isic_name + ) + + not_for_webtool <- transition_risk_profile( + emissions_profile = toy_emissions_profile, + sector_profile = toy_sector_profile, + co2 = toy_emissions_profile_products_ecoinvent, + all_activities_scenario_sectors = toy_all_activities_scenario_sectors, + scenarios = toy_sector_profile_any_scenarios, + for_webtool = FALSE + ) + + for_webtool <- transition_risk_profile( + emissions_profile = toy_emissions_profile, + sector_profile = toy_sector_profile, + co2 = toy_emissions_profile_products_ecoinvent, + all_activities_scenario_sectors = toy_all_activities_scenario_sectors, + scenarios = toy_sector_profile_any_scenarios, + for_webtool = TRUE + ) + + expect_equal(names(for_webtool), names(not_for_webtool)) + + not_for_webtool_company <- not_for_webtool |> + unnest_company() |> + ncol() + for_webtool_company <- for_webtool |> + unnest_company() |> + ncol() + expect_true(for_webtool_company < not_for_webtool_company) +}) + +test_that("case 3 companies are identified correctly", { + # To identify which companies belong to Case 3, please follow this link: + # https://github.com/2DegreesInvesting/TiltDevProjectMGMT/issues/169#issuecomment-2284344632 + case3_companies <- tribble( + # styler: off + ~companies_id, ~product, ~matched_activity_name, ~sector_target, + "comp", "a", "market for tap water", 2.0, + "comp", "b", "market for tap water", NA_real_, + "comp", "c", NA_character_, 2.0, + "comp", "d", NA_character_, NA_real_, + "case_3_comp", "a", NA_character_, NA_real_, + "case_3_comp", "b", NA_character_, NA_real_ + # styler: on + ) + result <- identify_case3_companies(case3_companies) + + expected_case3_company <- "case_3_comp" + expect_true(unique(result$companies_id) == expected_case3_company) +}) + +test_that("All columns are rounded off to 4 decimal places", { + round_cols <- tribble( + # styler: off + ~character_col, ~logical_col, ~numerical_col, + "comp", TRUE, 2.9393876, + "comp", FALSE, NA_real_, + "comp", TRUE, 4.5895959 + # styler: on + ) + + result <- round_off_to_4_decimal_places_impl(round_cols) + expect_true(all(result$numerical_col == round(result$numerical_col, 4), na.rm = TRUE)) +}) +