HW5

Quarto

options(repos = c(CRAN = "https://cran.rstudio.com/"))

library(tidyverse) 
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.4
✔ forcats   1.0.0     ✔ stringr   1.5.0
✔ ggplot2   3.4.4     ✔ tibble    3.2.1
✔ lubridate 1.9.2     ✔ tidyr     1.3.0
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(readxl) 
library(here) 
here() starts at /Users/sherri/IEA
library(dplyr)

file_path <- here("data-raw", "CM_Data_Explorer.xlsx")
file_path
[1] "/Users/sherri/IEA/data-raw/CM_Data_Explorer.xlsx"
ev_data <- read_excel(file_path, sheet = "2.3 EV")
New names:
• `` -> `...2`
• `` -> `...3`
• `` -> `...4`
• `` -> `...5`
• `` -> `...6`
• `` -> `...7`
• `` -> `...8`
• `` -> `...9`
• `` -> `...10`
• `` -> `...11`
• `` -> `...12`
• `` -> `...13`
• `` -> `...14`
• `` -> `...15`
• `` -> `...16`
• `` -> `...17`
• `` -> `...18`
• `` -> `...19`
• `` -> `...20`
• `` -> `...21`
• `` -> `...22`
• `` -> `...23`
ev_data
# A tibble: 92 × 23
   Mineral demand for el…¹   ...2 ...3  ...4    ...5   ...6   ...7   ...8   ...9
   <chr>                    <dbl> <lgl> <chr>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
 1 <NA>                      NA   NA    <NA>    NA     NA     NA     NA     NA  
 2 <NA>                      NA   NA    Stat…   NA     NA     NA     NA     NA  
 3 <NA>                    2022   NA    2025  2030   2035   2040   2045   2050  
 4 <NA>                      NA   NA    <NA>    NA     NA     NA     NA     NA  
 5 Constrained nickel sup…   NA   NA    <NA>    NA     NA     NA     NA     NA  
 6 Copper                   381.  NA    616.… 1389.  1736.  2233.  2418.  2313. 
 7 Cobalt                    63.5 NA    61.2…   38.0   29.1   35.4   40.9   47.4
 8 Graphite                 557.  NA    935.… 1590.  1782.  1691.  1492.  1077. 
 9 Lithium                   69.6 NA    122.…  219.   307.   407.   450.   413. 
10 Manganese                 74.5 NA    53.8…  156.   336.   533.   712.   858. 
# ℹ 82 more rows
# ℹ abbreviated name: ¹​`Mineral demand for electric vehicles (kt)`
# ℹ 14 more variables: ...10 <lgl>, ...11 <chr>, ...12 <dbl>, ...13 <dbl>,
#   ...14 <dbl>, ...15 <dbl>, ...16 <dbl>, ...17 <lgl>, ...18 <chr>,
#   ...19 <dbl>, ...20 <dbl>, ...21 <dbl>, ...22 <dbl>, ...23 <dbl>
read_ev_data_sheet <- partial(
  .f = read_excel,
  path = file_path,
  sheet = "2.3 EV",
  col_names = FALSE)

sheet_header <- read_ev_data_sheet(range = "A4:W5")
New names:
• `` -> `...1`
• `` -> `...2`
• `` -> `...3`
• `` -> `...4`
• `` -> `...5`
• `` -> `...6`
• `` -> `...7`
• `` -> `...8`
• `` -> `...9`
• `` -> `...10`
• `` -> `...11`
• `` -> `...12`
• `` -> `...13`
• `` -> `...14`
• `` -> `...15`
• `` -> `...16`
• `` -> `...17`
• `` -> `...18`
• `` -> `...19`
• `` -> `...20`
• `` -> `...21`
• `` -> `...22`
• `` -> `...23`
sheet_header
# A tibble: 2 × 23
  ...1   ...2 ...3  ...4    ...5  ...6  ...7  ...8  ...9 ...10 ...11 ...12 ...13
  <lgl> <dbl> <lgl> <chr>  <dbl> <dbl> <dbl> <dbl> <dbl> <lgl> <chr> <dbl> <dbl>
1 NA       NA NA    State…    NA    NA    NA    NA    NA NA    Anno…    NA    NA
2 NA     2022 NA    2025    2030  2035  2040  2045  2050 NA    2025   2030  2035
# ℹ 10 more variables: ...14 <dbl>, ...15 <dbl>, ...16 <dbl>, ...17 <lgl>,
#   ...18 <chr>, ...19 <dbl>, ...20 <dbl>, ...21 <dbl>, ...22 <dbl>,
#   ...23 <dbl>
sheet_header_processed <- sheet_header |> 
  t() |>
  as_tibble() |>
  rename(scenario = V1, year = V2) |>
  fill(scenario) |>
  replace_na(list(scenario = "Current Year"))
Warning: The `x` argument of `as_tibble.matrix()` must have unique column names if
`.name_repair` is omitted as of tibble 2.0.0.
ℹ Using compatibility `.name_repair`.
sheet_header_processed
# A tibble: 23 × 2
   scenario                 year 
   <chr>                    <chr>
 1 Current Year             <NA> 
 2 Current Year             2022 
 3 Current Year             <NA> 
 4 Stated policies scenario 2025 
 5 Stated policies scenario 2030 
 6 Stated policies scenario 2035 
 7 Stated policies scenario 2040 
 8 Stated policies scenario 2045 
 9 Stated policies scenario 2050 
10 Stated policies scenario <NA> 
# ℹ 13 more rows
Technology <- read_ev_data_sheet(range = "A7") |> 
  pull()
New names:
• `` -> `...1`
Technology
[1] "Constrained nickel supply"
mineral_info <- read_ev_data_sheet(range = "A8:W19")
New names:
• `` -> `...1`
• `` -> `...2`
• `` -> `...3`
• `` -> `...4`
• `` -> `...5`
• `` -> `...6`
• `` -> `...7`
• `` -> `...8`
• `` -> `...9`
• `` -> `...10`
• `` -> `...11`
• `` -> `...12`
• `` -> `...13`
• `` -> `...14`
• `` -> `...15`
• `` -> `...16`
• `` -> `...17`
• `` -> `...18`
• `` -> `...19`
• `` -> `...20`
• `` -> `...21`
• `` -> `...22`
• `` -> `...23`
mineral_info
# A tibble: 12 × 23
   ...1         ...2 ...3     ...4    ...5    ...6    ...7    ...8    ...9 ...10
   <chr>       <dbl> <lgl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl> <lgl>
 1 Copper    3.81e+2 NA    6.17e+2 1.39e+3 1.74e+3 2.23e+3 2.42e+3 2.31e+3 NA   
 2 Cobalt    6.35e+1 NA    6.12e+1 3.80e+1 2.91e+1 3.54e+1 4.09e+1 4.74e+1 NA   
 3 Graphite  5.57e+2 NA    9.36e+2 1.59e+3 1.78e+3 1.69e+3 1.49e+3 1.08e+3 NA   
 4 Lithium   6.96e+1 NA    1.23e+2 2.19e+2 3.07e+2 4.07e+2 4.50e+2 4.13e+2 NA   
 5 Manganese 7.45e+1 NA    5.39e+1 1.56e+2 3.36e+2 5.33e+2 7.12e+2 8.58e+2 NA   
 6 Nickel    3.13e+2 NA    5.54e+2 5.13e+2 5.89e+2 6.30e+2 6.92e+2 6.88e+2 NA   
 7 Silicon   8.70e+0 NA    4.05e+1 1.39e+2 2.24e+2 3.52e+2 3.74e+2 3.73e+2 NA   
 8 Neodymium 3.96e+0 NA    7.25e+0 1.22e+1 1.51e+1 1.88e+1 2.18e+1 2.29e+1 NA   
 9 Dysprosi… 4.13e-1 NA    7.41e-1 1.21e+0 1.48e+0 1.84e+0 2.13e+0 2.23e+0 NA   
10 Praseody… 5.94e-1 NA    1.09e+0 1.83e+0 2.27e+0 2.83e+0 3.27e+0 3.43e+0 NA   
11 Terbium   8.06e-2 NA    1.48e-1 2.52e-1 3.14e-1 3.91e-1 4.52e-1 4.74e-1 NA   
12 Total EV  1.47e+3 NA    2.39e+3 4.06e+3 5.02e+3 5.91e+3 6.21e+3 5.80e+3 NA   
# ℹ 13 more variables: ...11 <dbl>, ...12 <dbl>, ...13 <dbl>, ...14 <dbl>,
#   ...15 <dbl>, ...16 <dbl>, ...17 <lgl>, ...18 <dbl>, ...19 <dbl>,
#   ...20 <dbl>, ...21 <dbl>, ...22 <dbl>, ...23 <dbl>
#Or
Technology_range <- "A7"
mineral_info_range <- "A8:W19"

Technology <- read_ev_data_sheet(range = Technology_range) |> 
  pull()
New names:
• `` -> `...1`
mineral_info <- read_ev_data_sheet(range = mineral_info_range)
New names:
• `` -> `...1`
• `` -> `...2`
• `` -> `...3`
• `` -> `...4`
• `` -> `...5`
• `` -> `...6`
• `` -> `...7`
• `` -> `...8`
• `` -> `...9`
• `` -> `...10`
• `` -> `...11`
• `` -> `...12`
• `` -> `...13`
• `` -> `...14`
• `` -> `...15`
• `` -> `...16`
• `` -> `...17`
• `` -> `...18`
• `` -> `...19`
• `` -> `...20`
• `` -> `...21`
• `` -> `...22`
• `` -> `...23`
mineral_info_col_names <- names(mineral_info)
mineral_info_col_names
 [1] "...1"  "...2"  "...3"  "...4"  "...5"  "...6"  "...7"  "...8"  "...9" 
[10] "...10" "...11" "...12" "...13" "...14" "...15" "...16" "...17" "...18"
[19] "...19" "...20" "...21" "...22" "...23"
sheet_headers_and_col_names <- sheet_header_processed |> 
  add_column(mineral_info_col_names = mineral_info_col_names)
sheet_headers_and_col_names
# A tibble: 23 × 3
   scenario                 year  mineral_info_col_names
   <chr>                    <chr> <chr>                 
 1 Current Year             <NA>  ...1                  
 2 Current Year             2022  ...2                  
 3 Current Year             <NA>  ...3                  
 4 Stated policies scenario 2025  ...4                  
 5 Stated policies scenario 2030  ...5                  
 6 Stated policies scenario 2035  ...6                  
 7 Stated policies scenario 2040  ...7                  
 8 Stated policies scenario 2045  ...8                  
 9 Stated policies scenario 2050  ...9                  
10 Stated policies scenario <NA>  ...10                 
# ℹ 13 more rows
mineral_info_long <- mineral_info |> 
  rename(indicator = `...1`) |> 
  pivot_longer(cols = -indicator,
               names_to = "mineral_info_col_names") |> 
  add_column(Technology)

mineral_info_long
# A tibble: 264 × 4
   indicator mineral_info_col_names value Technology               
   <chr>     <chr>                  <dbl> <chr>                    
 1 Copper    ...2                    381. Constrained nickel supply
 2 Copper    ...3                     NA  Constrained nickel supply
 3 Copper    ...4                    617. Constrained nickel supply
 4 Copper    ...5                   1389. Constrained nickel supply
 5 Copper    ...6                   1736. Constrained nickel supply
 6 Copper    ...7                   2233. Constrained nickel supply
 7 Copper    ...8                   2418. Constrained nickel supply
 8 Copper    ...9                   2313. Constrained nickel supply
 9 Copper    ...10                    NA  Constrained nickel supply
10 Copper    ...11                   732. Constrained nickel supply
# ℹ 254 more rows
combined_data <- mineral_info_long |> 
  left_join(sheet_headers_and_col_names, by = join_by(mineral_info_col_names)) |> 
  filter(!is.na(year)) |> 
  mutate(unit = "kiloton", year = as.integer(year)) |> 
  select(Technology, indicator, scenario, unit, year, value)

combined_data
# A tibble: 228 × 6
   Technology                indicator scenario                unit   year value
   <chr>                     <chr>     <chr>                   <chr> <int> <dbl>
 1 Constrained nickel supply Copper    Current Year            kilo…  2022  381.
 2 Constrained nickel supply Copper    Stated policies scenar… kilo…  2025  617.
 3 Constrained nickel supply Copper    Stated policies scenar… kilo…  2030 1389.
 4 Constrained nickel supply Copper    Stated policies scenar… kilo…  2035 1736.
 5 Constrained nickel supply Copper    Stated policies scenar… kilo…  2040 2233.
 6 Constrained nickel supply Copper    Stated policies scenar… kilo…  2045 2418.
 7 Constrained nickel supply Copper    Stated policies scenar… kilo…  2050 2313.
 8 Constrained nickel supply Copper    Announced pledges scen… kilo…  2025  732.
 9 Constrained nickel supply Copper    Announced pledges scen… kilo…  2030 2113.
10 Constrained nickel supply Copper    Announced pledges scen… kilo…  2035 3587.
# ℹ 218 more rows
#Build a function

read_ev_mineral_table <-
  function(Technology_range, mineral_info_range) {
  
Technology <- read_ev_data_sheet(range = Technology_range) |> 
  pull()

mineral_info <- read_ev_data_sheet(range = mineral_info_range)

mineral_info_col_names <- names(mineral_info)

sheet_headers_and_col_names <- sheet_header_processed |> 
  add_column(mineral_info_col_names = mineral_info_col_names)

mineral_info_long <- mineral_info |> 
  rename(indicator = `...1`) |> 
  pivot_longer(cols = -indicator,
               names_to = "mineral_info_col_names") |> 
  add_column(Technology)

combined_data <- mineral_info_long |> 
  left_join(sheet_headers_and_col_names, by = join_by(mineral_info_col_names)) |> 
  filter(!is.na(year)) |> 
  mutate(unit = "kiloton", year = as.integer(year)) |> 
  select(Technology, indicator, scenario, unit, year, value)

combined_data}
constrained_nickel_supply_table <- read_ev_mineral_table(
  Technology_range = "A7",
  mineral_info_range = "A8:W19")
New names:
New names:
• `` -> `...1`
write_csv(constrained_nickel_supply_table,here("data", "constrained_nickel_supply_table.csv"))

wider_use_of_silicon_rich_anodes_table <- read_ev_mineral_table(
  Technology_range = "A22",
  mineral_info_range = "A23:W34")
New names:
New names:
• `` -> `...1`
write_csv(wider_use_of_silicon_rich_anodes_table,here("data", "wider_use_of_silicon_rich_anodes_table.csv"))

faster_uptake_of_solid_state_batteries_table <- read_ev_mineral_table(
  Technology_range = "A37",
  mineral_info_range = "A38:W49")
New names:
New names:
• `` -> `...1`
write_csv(faster_uptake_of_solid_state_batteries_table,here("data", "faster_uptake_of_solid_state_batteries_table.csv"))

lower_battery_sizes_table <- read_ev_mineral_table(
  Technology_range = "A52",
  mineral_info_range = "A53:W64")
New names:
New names:
• `` -> `...1`
write_csv(lower_battery_sizes_table,here("data", "lower_battery_sizes_table.csv"))

STEPS_base_case_table <- read_ev_mineral_table(
  Technology_range = "A82",
  mineral_info_range = "A83:W94")
New names:
New names:
• `` -> `...1`
write_csv(STEPS_base_case_table,here("data", "STEPS_base_case_table.csv"))
data1 <- read_csv("/Users/sherri/IEA/data/constrained_nickel_supply_table.csv")
Rows: 228 Columns: 6
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (4): Technology, indicator, scenario, unit
dbl (2): year, value

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
copper_data1 <- data1 %>% 
  filter(indicator == "Copper")

p <- ggplot(copper_data1, aes(x = factor(year), y = value, fill = scenario)) +
  geom_bar(stat = "identity", position = position_dodge()) + # Use dodge position for side-by-side bars
  theme_minimal() + 
  labs(title = "Projected Copper Supply by Scenario",
       x = "Year",
       y = "Supply (kiloton)",
       fill = "Scenario") +
  scale_fill_brewer(palette = "Set2") 

print(p)

#Net Zero scenario encourage the largest growth in projected copper supply

selected_data <- data1 %>%
  filter(indicator %in% c("Copper", "Cobalt"))

p2 <- ggplot(selected_data, aes(x = factor(year), y = value, fill = indicator)) +
  geom_bar(stat = "identity", position = position_dodge(), color = "black") + 
  theme_minimal() + 
  labs(title = "Comparison between Projected Supply of Copper and Cobalt",
       x = "Year",
       y = "Supply (kiloton)",
       fill = "Material") +
  scale_fill_brewer(palette = "Paired") 

print(p2)

#Copper is in a dominant position when it comes to the volume.

growth_data <- data1 %>%
  filter(indicator %in% c("Copper", "Cobalt")) %>%
  arrange(indicator, scenario, year) %>%
  group_by(indicator, scenario) %>%
  mutate(growth_rate = (value / lag(value) - 1) * 100) %>%
  ungroup()

growth_data <- growth_data %>%
  drop_na()

p3 <- ggplot(growth_data, aes(x = year, y = growth_rate, color = indicator, group = interaction(indicator, scenario))) +
  geom_line() +
  geom_point() +
  facet_wrap(~scenario) + 
  theme_minimal() + 
  labs(title = "Annual Growth Rate of Copper and Cobalt Supply by Scenario",
       x = "Year",
       y = "Growth Rate (%)",
       color = "Material") +
  scale_color_brewer(palette = "Set1") 

print(p3)

#Despite Cobalt is way much irrelavant in its volume when compared with Copper, it shows a steady positive annual growth rate.

copper_lower <- lower_battery_sizes_table %>%
  filter(indicator == "Copper")

ggplot(copper_lower, aes(x = year, y = value)) +
  geom_line(color = "steelblue", size = 1) +
  geom_point(color = "darkblue") +
  theme_minimal() +
  facet_wrap(~scenario) +
  labs(title = "Copper Supply Trends under Lower Battery Sizes Scenario",
       x = "Year",
       y = "Supply (kiloton)")
Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
ℹ Please use `linewidth` instead.
`geom_line()`: Each group consists of only one observation.
ℹ Do you need to adjust the group aesthetic?

#In all the scenarios, the policy will encourage a spike in the volumn fist and the growth speed will slow down.

data2 <- wider_use_of_silicon_rich_anodes_table %>%
  filter(indicator %in% c("Copper", "Cobalt"))

ggplot(data2, aes(x = year, y = value, fill = indicator)) +
  geom_area(alpha = 0.5, position = "stack") +
  theme_minimal() +
  facet_wrap(~scenario) +
  labs(title = "Cumulative Supply of Copper and Cobalt Over Time",
       x = "Year",
       y = "Supply (kiloton)",
       fill = "Material")

#The graphs suggest that aggressive climate policies and technological advancements aimed at net-zero emissions by 2050 could lead to a substantial increase in the demand for copper and cobalt compared to current policy scenarios.