The United States’ economic and national security depend on the secure supply of critical minerals, essential for industries such as defense, energy, and technology. Many of these minerals are sourced from countries outside the US, raising concerns about supply chain vulnerabilities during geopolitical tensions or crises. This study will catalog the sources of these minerals, categorizing each country as an ally, competitor, or neutral party, to assess the reliability of these sources under stress. By analyzing dependencies and geopolitical risks, the research aims to highlight the potential impacts of supply disruptions on US industries.
The dataset includes information on the sources of minerals listed in the 2022 USGS List of Critical Minerals, combined with the U.S. Geological Survey Mineral Commodity Summaries 2024 Data Release. It contains the names of critical minerals, their primary source countries, and a classification of each source country as an ally, competitor, or neutral party based on geopolitical and economic relationships with the United States. The dataset also incorporates the World Bank’s political stability score for each country to assess the reliability of mineral sources under stressed circumstances, such as war or economic crises. Visualizations are included to show the global distribution of mineral sources and the potential impacts of supply disruptions on key US industries.
library(sf)
library(leaflet)
library(dplyr)
library(rnaturalearth)
library(rnaturalearthdata)
library(ggplot2)
library(tidyr)
df <- read.csv("https://raw.githubusercontent.com/suswong/DATA-608/refs/heads/main/MCS2024_Fig2_Net_Import_Reliance.csv")
source <- read.csv("https://raw.githubusercontent.com/suswong/DATA-608/refs/heads/main/MCS2024_Fig3_Major_Import_Sources.csv")
political <- read.csv("https://raw.githubusercontent.com/suswong/DATA-608/refs/heads/main/World%20Bank%20Political%20Stability.csv")
crit_minerals <-read.csv("https://raw.githubusercontent.com/suswong/DATA-608/refs/heads/main/MCS2024_T5_Critical_Minerals_Salient.csv")
minerals_usage <- read.csv("https://raw.githubusercontent.com/suswong/DATA-608/refs/heads/main/MCS2024_T4_Critical_Minerals_End_Use.csv")
data <- df
data$Commodity <- sapply(strsplit(data$Commodity, " "), `[`, 1)
data$Commodity <- gsub(",", "", data$Commodity)
data$Net_Import_Reliance_pct_2023 <- gsub("[<>]", "", data$Net_Import_Reliance_pct_2023)
data <- data %>%
select(Commodity, Net_Import_Reliance_pct_2023, Major_Import_Sources_2019_2022) %>%
mutate(Net_Import_Reliance_pct_2023 = as.numeric(Net_Import_Reliance_pct_2023))
political$Score <- as.numeric(political$Score)
political$stability_category <- cut(political$Score,
breaks = c(-Inf, -0.5, 0.5, Inf),
labels = c("Low", "Medium", "High"))
merged_df <- left_join(source, political, by = "Country")
country_alliance <- c(
"Australia" = "Ally", "Austria" = "Ally", "Belarus" = "Competitor", "Belgium" = "Ally",
"Bolivia" = "Neutral", "Brazil" = "Neutral", "Canada" = "Ally", "Chile" = "Neutral",
"China" = "Competitor", "Estonia" = "Ally", "Finland" = "Ally", "France" = "Ally",
"Gabon" = "Neutral", "Georgia" = "Neutral", "Germany" = "Ally", "Guyana" = "Neutral",
"India" = "Competitor", "Indonesia" = "Neutral", "Ireland" = "Ally", "Israel" = "Ally",
"Italy" = "Ally", "Jamaica" = "Neutral", "Japan" = "Ally", "Kazakhstan" = "Neutral",
"Madagascar" = "Neutral", "Malaysia" = "Neutral", "Mexico" = "Neutral", "Morocco" = "Neutral",
"Netherlands" = "Ally", "Norway" = "Ally", "Peru" = "Neutral", "Philippines" = "Neutral",
"Poland" = "Ally", "Russia" = "Competitor", "Saudi Arabia" = "Neutral", "South Africa" = "Neutral",
"South Korea" = "Ally", "Switzerland" = "Ally", "Taiwan" = "Ally", "Turkey" = "Neutral",
"Ukraine" = "Competitor", "Vietnam" = "Neutral"
)
merged_df <- merged_df %>%
mutate(alliance = country_alliance[Country])
minerals_sources_clean <- data %>%
separate_rows(Major_Import_Sources_2019_2022, sep = ", ") %>%
mutate(Major_Import_Sources_2019_2022 = trimws(Major_Import_Sources_2019_2022)) # Remove leading/trailing spaces
minerals_sources_with_alliance <- minerals_sources_clean %>%
left_join(merged_df, by = c("Major_Import_Sources_2019_2022" = "Country"))
dependency_summary <- minerals_sources_with_alliance %>%
group_by(alliance) %>%
summarise(total_minerals = n_distinct(Commodity))
minerals_usage <- minerals_usage %>%
mutate(Category = case_when(
grepl("battery|electronics|solar|fuel cell|display|circuit|optical|integrated", Primary.Applications, ignore.case = TRUE) ~ "Electronics & Energy",
grepl("metallurgy|construction|cement|industrial|fuel cells|lubricants", Primary.Applications, ignore.case = TRUE) ~ "Construction & Industry",
grepl("medical|cancer|nuclear|imaging|research|pharmaceuticals", Primary.Applications, ignore.case = TRUE) ~ "Healthcare & Research",
grepl("aerospace|defense|military|nuclear control rods", Primary.Applications, ignore.case = TRUE) ~ "Defense & Aerospace",
grepl("rare earth|permanent magnets|lasers|catalysts|data storage|fiber optics", Primary.Applications, ignore.case = TRUE) ~ "Rare Earth Elements",
grepl("catalytic converters|platinum|rhodium|iridium|ruthenium|palladium", Primary.Applications, ignore.case = TRUE) ~ "Catalysts & Precious Metals",
TRUE ~ "Other"
))
category_summary <- minerals_usage %>%
group_by(Category) %>%
tally()
ggplot(category_summary, aes(x = reorder(Category, n), y = n, fill = Category)) +
geom_bar(stat = "identity") +
theme_minimal() +
labs(title = "Minerals Usage by Category",
x = "Category",
y = "Number of Minerals") +
coord_flip()
This chart shows how much the U.S. depends on imports for critical minerals, with the countries classified as allies (green), competitors (red), or neutral (gray). Some minerals, like Yttrium and Tantalum, have a high reliance on competitors (China), while others like Nickel and Lithium come from a mix of allies and competitors. This helps highlight potential risks in the U.S. mineral supply, especially from competitors.
crit_minerals <- crit_minerals[!is.na(crit_minerals$Net_Import_Reliance),]
ggplot(crit_minerals, aes(x = reorder(Critical_mineral, Net_Import_Reliance),
y = Net_Import_Reliance,
fill = Alliance)) +
geom_bar(stat = "identity") +
labs(title = "Mineral Dependency: Net Import Reliance by Mineral",
x = "Mineral",
y = "Net Import Reliance (%)") +
theme_minimal() +
coord_flip() + # Flip the chart for better readability
scale_fill_manual(values = c("Ally" = "green", "Competitor" = "red", "Neutral" = "gray")) +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) # Rotate x-axis labels if needed
crit_minerals$Reliance_Weight <- crit_minerals$Net_Import_Reliance / 100
dependency_by_alliance <- aggregate(Reliance_Weight ~ Alliance, data = crit_minerals, sum)
#ggplot(dependency_by_alliance, aes(x = Alliance, y = Reliance_Weight, fill = Alliance)) +
# geom_bar(stat = "identity", show.legend = FALSE) +
# theme_minimal() +
# labs(title = "U.S. Dependency on Mineral Imports by Alliance Status",
# x = "Alliance Status",
# y = "Total Weighted Reliance (%)") +
# scale_fill_brewer(palette = "Set1")
country_alliance <- c(
"Australia" = "Ally", "Austria" = "Ally", "Belarus" = "Competitor", "Belgium" = "Ally",
"Bolivia" = "Neutral", "Brazil" = "Neutral", "Canada" = "Ally", "Chile" = "Neutral",
"China" = "Competitor", "Estonia" = "Ally", "Finland" = "Ally", "France" = "Ally",
"Gabon" = "Neutral", "Georgia" = "Neutral", "Germany" = "Ally", "Guyana" = "Neutral",
"India" = "Competitor", "Indonesia" = "Neutral", "Ireland" = "Ally", "Israel" = "Ally",
"Italy" = "Ally", "Jamaica" = "Neutral", "Japan" = "Ally", "Kazakhstan" = "Neutral",
"Madagascar" = "Neutral", "Malaysia" = "Neutral", "Mexico" = "Neutral", "Morocco" = "Neutral",
"Netherlands" = "Ally", "Norway" = "Ally", "Peru" = "Neutral", "Philippines" = "Neutral",
"Poland" = "Ally", "Russia" = "Competitor", "Saudi Arabia" = "Neutral", "South Africa" = "Neutral",
"South Korea" = "Ally", "Switzerland" = "Ally", "Taiwan" = "Ally", "Turkey" = "Neutral",
"Ukraine" = "Competitor", "Vietnam" = "Neutral"
)
merged_df <- merged_df %>%
mutate(alliance = country_alliance[Country])
world <- ne_countries(scale = "medium", returnclass = "sf")
# Merge your data with the world map data
map_data <- world %>%
left_join(political, by = c("name" = "Country"))
# Create the interactive map
leaflet(map_data) %>%
addTiles() %>%
addPolygons(
fillColor = ~case_when(
stability_category == "Low" ~ "red",
stability_category == "Medium" ~ "yellow",
stability_category == "High" ~ "green"
),
weight = 1,
opacity = 1,
color = "black",
dashArray = "3",
fillOpacity = 0.7,
popup = ~paste(name, "<br>Stability Score: ", Score,
"<br>Category: ", stability_category)
) %>%
addLegend(
position = "bottomright",
pal = colorFactor(c("red", "yellow", "green"), domain = c("Low", "Medium", "High")),
values = ~stability_category,
title = "Political Stability"
)
This bar chart shows the number of critical minerals sourced from each country, categorized by political stability. China, Canada, and Germany are the top sources, with varying levels of political stability. China has the highest number of minerals but faces low political stability, indicating potential supply risks. Countries like Canada and Australia, with high stability, offer more reliable sources. This visualization highlights the geopolitical risks in mineral supply chains, helping assess vulnerabilities in times of global stress.
merged_df <- na.omit(merged_df)
ggplot(merged_df, aes(y = reorder(Country, Commodity_Count), x = Commodity_Count, fill = stability_category)) +
geom_bar(stat = "identity") +
scale_fill_manual(
values = c("Low" = "#E57373", "Medium" = "#FFF176", "High" = "#81C784") # Custom colors for stability categories
) +
labs(
title = "Critical Mineral Sourced by Country and Political Stability",
x = "Number of Minerals",
y = "Country",
fill = "Political Stability"
) +
theme_minimal() +
theme(
text = element_text(size = 10),
plot.title = element_text(hjust = 0.5),
axis.text.y = element_text( hjust = 1) # Rotate y-axis labels for readability
)