The US Geological Survey publishes a list of Strategic Minerals ( https://www.usgs.gov/news/national-news-release/us-geological-survey-releases-2022-list-critical-minerals ). Having a secure supply of these minerals is essential to our security and economic prosperity. However, many of these minerals are sourced from outside of the US. This assignment is to develop a reference catalog of the source or sources of each of these minerals and a judgement on the reliability of each source under stressed circumstance (e.g. war, economic crisis, etc.) Notes: 1. You will need to identify a source or sources for each of the minerals in the 2022 List of Critical Minerals 2. You will need to categorize each source country as an ally, a competitor or a neutral party. 3. You will need to develop data visualizations that tell the story of source dependency and shortfall impact.
The Energy Act of 2020 and President Biden’s Bipartisan Infrastructure Law underscore the significance of critical minerals for the economic and national security of the United States. These minerals, essential to various industries, are susceptible to supply chain disruptions. They are vital for manufacturing products for both the economy and national security.The US Geological Survey (USGS) is researching the potential of critical minerals within the US. This includes updating mapping of these minerals, both in-ground and in mine wastes.
# Load required libraries
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.1 ✔ tibble 3.2.1
## ✔ lubridate 1.9.3 ✔ tidyr 1.3.1
## ✔ 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(ggplot2)
library(ggthemes)
library(plotly)
##
## Attaching package: 'plotly'
##
## The following object is masked from 'package:ggplot2':
##
## last_plot
##
## The following object is masked from 'package:stats':
##
## filter
##
## The following object is masked from 'package:graphics':
##
## layout
library(readr)
# Remove warnings
options(warn=-1)
Source Data: https://www.kaggle.com/datasets/ramjasmaurya/mineral-ores-around-the-world
# Load data
minerals_data <- read_csv("Mineral ores round the world.csv")
## Rows: 304632 Columns: 22
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (20): site_name, region, country, state, county, com_type, commod1, comm...
## dbl (2): latitude, longitude
##
## ℹ 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.
# Filter rows where "country" is "United States"
us_minerals_data <- subset(minerals_data, country == "United States")
# Print the dimensions of the dataframe
cat("The file has", ncol(us_minerals_data), "columns and", nrow(us_minerals_data), "rows\n")
## The file has 22 columns and 266599 rows
# Display the first 3 rows of the dataframe
head(us_minerals_data)
## # A tibble: 6 × 22
## site_name latitude longitude region country state county com_type commod1
## <chr> <dbl> <dbl> <chr> <chr> <chr> <chr> <chr> <chr>
## 1 Lookout Prosp… 55.1 -132. <NA> United… Alas… <NA> M Copper
## 2 Lucky Find Pr… 55.5 -133. <NA> United… Alas… <NA> M Copper
## 3 Mccullough Pr… 56.0 -133. <NA> United… Alas… <NA> M Copper
## 4 Lucky Jim Cla… 55.5 -133. <NA> United… Alas… <NA> M Gold
## 5 Matilda Occur… 55.1 -132. <NA> United… Alas… <NA> M Gold
## 6 Marion Prospe… 55.1 -132. <NA> United… Alas… <NA> M Copper
## # ℹ 13 more variables: commod2 <chr>, commod3 <chr>, oper_type <chr>,
## # dep_type <chr>, prod_size <chr>, dev_stat <chr>, ore <chr>, gangue <chr>,
## # work_type <chr>, names <chr>, ore_ctrl <chr>, hrock_type <chr>,
## # arock_type <chr>
# Calculate missing values percentage per column
missing_percentage <- colMeans(is.na(us_minerals_data)) * 100
# Get the names of columns with missing values exceeding 20%
columns_to_remove <- names(missing_percentage[missing_percentage > 20])
# Remove columns with more than 20% missing values
us_minerals_data <- us_minerals_data[, !(names(us_minerals_data) %in% columns_to_remove)]
# Remove the "county" column
us_minerals_data <- subset(us_minerals_data, select = -county)
head(us_minerals_data)
## # A tibble: 6 × 9
## site_name latitude longitude country state com_type commod1 oper_type dev_stat
## <chr> <dbl> <dbl> <chr> <chr> <chr> <chr> <chr> <chr>
## 1 Lookout … 55.1 -132. United… Alas… M Copper Unknown Occurre…
## 2 Lucky Fi… 55.5 -133. United… Alas… M Copper Unknown Occurre…
## 3 Mccullou… 56.0 -133. United… Alas… M Copper Unknown Occurre…
## 4 Lucky Ji… 55.5 -133. United… Alas… M Gold Unknown Occurre…
## 5 Matilda … 55.1 -132. United… Alas… M Gold Unknown Occurre…
## 6 Marion P… 55.1 -132. United… Alas… M Copper Unknown Occurre…
# Remove rows with missing values from the dataset
cleaned_minearls <- na.omit(us_minerals_data)
head(cleaned_minearls)
## # A tibble: 6 × 9
## site_name latitude longitude country state com_type commod1 oper_type dev_stat
## <chr> <dbl> <dbl> <chr> <chr> <chr> <chr> <chr> <chr>
## 1 Lookout … 55.1 -132. United… Alas… M Copper Unknown Occurre…
## 2 Lucky Fi… 55.5 -133. United… Alas… M Copper Unknown Occurre…
## 3 Mccullou… 56.0 -133. United… Alas… M Copper Unknown Occurre…
## 4 Lucky Ji… 55.5 -133. United… Alas… M Gold Unknown Occurre…
## 5 Matilda … 55.1 -132. United… Alas… M Gold Unknown Occurre…
## 6 Marion P… 55.1 -132. United… Alas… M Copper Unknown Occurre…
# Print the number of missing values in each column
print(colSums(is.na(cleaned_minearls)))
## site_name latitude longitude country state com_type commod1 oper_type
## 0 0 0 0 0 0 0 0
## dev_stat
## 0
# Read the CSV file
state_names <- read_csv("state_names.csv")
## Rows: 51 Columns: 4
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (3): State, Abbreviation, Alpha code
## dbl (1): Code
##
## ℹ 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.
state_names <- subset(state_names, select = -c(Code, Abbreviation))
# Change column name using colnames() function
colnames(state_names)[which(colnames(state_names) == "State")] <- "state"
colnames(state_names)[which(colnames(state_names) == "Alpha code")] <- "Abbreviation"
# Merge us_minerals_data and state_names data frames based on the "state" column
df_usa <- merge(cleaned_minearls, state_names, by = "state")
# Remove rows containing NA values
df_clean_rows <- na.omit(df_usa)
# Keep rows where the "open_type" column contains "unknown"
minerals_df <- df_clean_rows[df_clean_rows$dev_stat == "Occurrence", ]
minerals_df <- df_clean_rows[df_clean_rows$dev_stat == "Occurrence", ]
dim(minerals_df)
## [1] 47931 10
# Count the number of minerals in the commod1 column
num_minerals <- length(unique(minerals_df$commod1))
# Filter the list of Critical Mineral 2022 dataset
Critical_Minierals_df <- minerals_df[minerals_df$commod1 %in% c("Aluminum", "Antimony", "Arsenic", "Barium-Barite", "Beryllium", "Bismuth", "Cerium", "Cesium", "Chromium", "Cobalt", "Dysprosium", "Erbium", "Europium", "Fluorspar", "Gadolinium", "Gallium", "Germanium", "Graphite", "Hafnium", "Indium", "Iridium", "Lanthanum", "Lithium", "Lutetium", "Magnesium", "Manganese", "Neodymium", "Nickel", "Niobium", "Palladium", "Platinum", "Praseodymium", "Rhodium", "Rubidium", "Ruthenium", "Samarium", "Scandium", "Tantalum", "Tellurium", "Terbium", "Thulium", "Tin", "Titanium", "Tungsten", "Vanadium", "Ytterbium", "Yttrium", "Zinc", "Zirconium"), ]
# Create a table of counts of critical minierals in US
counts <- table(Critical_Minierals_df$commod1)
# Convert the table to a data frame
counts_df <- as.data.frame(counts)
# Rename the columns
names(counts_df) <- c("Minerals", "Counts")
# Print the data table
print(counts_df)
## Minerals Counts
## 1 Aluminum 446
## 2 Antimony 186
## 3 Arsenic 28
## 4 Barium-Barite 487
## 5 Beryllium 136
## 6 Bismuth 11
## 7 Chromium 1451
## 8 Cobalt 25
## 9 Gallium 6
## 10 Germanium 1
## 11 Graphite 127
## 12 Lithium 17
## 13 Manganese 1134
## 14 Nickel 155
## 15 Palladium 3
## 16 Platinum 24
## 17 Ruthenium 1
## 18 Scandium 1
## 19 Tantalum 7
## 20 Tin 155
## 21 Titanium 113
## 22 Tungsten 926
## 23 Vanadium 28
## 24 Zinc 383
## 25 Zirconium 4
# Create a bar plot
ggplot(Critical_Minierals_df, aes(x = state, fill = commod1)) +
geom_bar() +
labs(x = "State", y = "Count", title = "Statewise Occourence of Critical Minerals in US") +
theme(axis.text.x = element_text(angle = 90, hjust = 1))
Critical minerals and materials serve as essential components in numerous clean energy technologies like solar panels, wind turbines, electric vehicle batteries, and energy storage systems.
As we strive towards a cleaner energy and industrial landscape, the demand for critical minerals grows. Currently, estimated over 85% of the United States’ critical mineral supply originates from foreign sources. Importantly, domestic production is absent for 25 out of 50 critical minerals.
By fostering a robust domestic supply of critical minerals, we can diminish our reliance on foreign sources. This endeavor will not only create high-paying manufacturing jobs but also bolster communities nationwide that have traditionally relied on mining and energy production.
The United States heavily depends on imports of specific mineral commodities crucial for its security and economic well-being. This reliance on foreign sources poses a strategic vulnerability, impacting both the nation’s economy and military readiness. Adverse actions by foreign governments, natural disasters, or other unforeseen events can disrupt the supply of these essential minerals, posing significant challenges to the US.
Source: (https://en.wikipedia.org/wiki/Foreign_relations_of_the_United_States)
# Read the CSV data directly from the web link
df <- read_csv("https://www.sciencebase.gov/catalog/file/get/5e616381e4b01d509255c7b6?f=__disk__9f%2Fe3%2F8b%2F9fe38b3bec1b9bc404b14578a226c080fcecf834&allowOpen=true")
## Rows: 1366 Columns: 103
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (32): LAB_ID, PREVIOUS_LAB_ID1, PREVIOUS_LAB_ID2, FIELD_ID, JOB_ID, PREV...
## dbl (69): LATITUDE, LONGITUDE, LATITUDE_COLLECT, LONGITUDE_COLLECT, Al_pct_A...
## lgl (2): PREVIOUS_LAB_ID3, PREVIOUS_JOB_ID3
##
## ℹ 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.
# Mapping countries to whether they are allies, neutral, or competitors
alliance_mapping <- c(
Chile = "Neutral",
`South Africa` = "Ally",
Finland = "Ally",
Mexico = "Neutral",
Indonesia = "Ally",
Norway = "Ally",
Canada = "Ally",
Russia = "Competitor",
Japan = "Ally",
Philippines = "Neutral",
Peru = "Neutral",
Cuba = "Competitor",
Australia = "Ally",
Burma = "Neutral",
Portugal = "Ally",
Sweden = "Ally",
China = "Competitor",
Mauritania = "Neutral",
Brazil = "Neutral",
Argentina = "Neutral",
Germany = "Ally",
Namibia = "Neutral",
Zambia = "Neutral",
India = "Neutral",
Poland = "Ally",
`Democratic Republic of Congo` = "Neutral",
Vietnam = "Neutral",
`Papua New Guinea` = "Neutral",
Honduras = "Neutral"
)
# Group by country and count the number of mineral samples
dat <- aggregate(LAB_ID ~ COUNTRY, data = df, FUN = length)
# Reset the index of the resulting data frame
dat <- dat[order(dat$LAB_ID, decreasing = TRUE), ]
# Map diplomatic relations and color based on the country
dat$relations <- alliance_mapping[match(dat$COUNTRY, names(alliance_mapping))]
# Filter out rows where the country is not "United States"
dat <- subset(dat, COUNTRY != "United States")
# Define custom color palette
custom_colors <- c("Ally" = "green", "Competitor" = "red", "Neutral" = "blue")
# Create the bar plot
ggplot(dat, aes(x = LAB_ID, y = COUNTRY, fill = relations)) +
geom_bar(stat = "identity", position = "dodge") +
labs(x = "Number of Mineral Samples Produced",
y = "Country",
title = "Number of Minerals Produced Internationally",
subtitle = "Allies of the United States have been producing critical minerals faster than enemies. \nHowever, changing diplomatic relations can always tip the balance") +
scale_fill_manual(values = custom_colors) + # Apply custom color palette
theme_minimal() +
theme(plot.title = element_text(size = 14, face = "bold"),
plot.subtitle = element_text(size = 10))
Remarkably, more than half of the consumption of approximately 43 out of 50 critical minerals and metals is met through imports.
The USGS’s list of Strategic Minerals serves as a critical reference point for understanding the sourcing landscape of minerals essential for national security and economic prosperity. While securing a stable supply of these minerals is imperative, the reality is that many of them originate from outside the United States. Therefore, the dependency of the United States on foreign sources for strategic minerals mitigates the risks associated with source dependency. This includes diversifying supply sources, investing in domestic production capabilities, and fostering international partnerships to ensure a resilient and secure supply chain of critical minerals.