library(tidyverse)
library(ggplot2)
library(gganimate)
library(plotly)
library(data.table)
library(sf)
library(gifski)
library(dplyr)
The transition to electric vehicles (EVs) is a critical component of global efforts to reduce greenhouse gas emissions and combat climate change. This analysis leverages the IEA Global EV Data 2024 dataset to explore key trends in EV adoption, sales, and infrastructure development across different regions and powertrain types. The dataset provides historical and projected data on EV sales, market share, and charging infrastructure, offering a comprehensive view of the evolving EV landscape.
Through a series of visualizations, we aim to answer the following questions:
Which countries are leading in EV sales over
time?
We identify the top 10 countries by EV sales and track their rankings
annually to understand regional trends and shifts in market
leadership.
How do different powertrain types (e.g., Battery Electric
Vehicles (BEVs), Plug-in Hybrid Electric Vehicles (PHEVs)) contribute to
global EV sales?
We analyze the growth trajectories of various powertrain types to assess
their market penetration and adoption rates.
What is the state of EV charging infrastructure in key
regions (e.g., USA, China, Europe)?
We compare the number of EV charging points to EV sales in these regions
to evaluate the adequacy of infrastructure development.
How has the global market share of EVs evolved over
time?
We examine the proportion of EV sales relative to total vehicle sales,
highlighting the growing importance of EVs in the automotive
market.
By addressing these questions, we aim to provide actionable insights into the current state and future potential of the global EV market, helping policymakers, industry stakeholders, and researchers make informed decisions.
# Load the dataset
file_path <- "C:/Users/T490/Downloads/IEA Global EV Data 2024.csv"
ev_data <- read.csv(file_path)
# Convert columns to appropriate types
ev_data <- ev_data %>%
mutate(
year = as.integer(year),
value = as.numeric(value)
) %>%
distinct() # Remove duplicates
# Convert data to data.table for efficient processing
dt <- data.table(ev_data)[parameter == "EV sales" & category == "Historical",
.(total_sales = sum(value)), by = .(region, year)]
# Remove unwanted regions
dt <- dt[!region %in% c("World", "Europe", "Rest of the world", "EU27")]
# Sort data by year and total sales, then assign rankings for each year
dt <- dt[order(year, -total_sales)] # Sort by year and sales
dt[, rank := frank(-total_sales), by = year] # Assign ranking per year (using frank for ranking)
# Filter top 10 countries for each year
dt_top10 <- dt[rank <= 10]
# Ensure that only 10 countries are plotted per year
dt_top10 <- dt_top10[!is.na(total_sales)] # Remove any NA values
# Create animated bar plot
g <- ggplot(dt_top10, aes(x = total_sales, y = factor(rank), fill = region)) +
geom_col() +
geom_text(aes(label = region), hjust = -0.2, vjust = 0.1, angle = 0, size = 2, color = 'black') +
scale_x_continuous(labels = scales::label_number(scale = 1e-3, suffix = "K")) + # Format x-axis in thousands
labs(
title = "Top 10 Countries by EV Sales Over Time",
subtitle = "Year: {closest_state}",
x = "Total EV Sales (Units)",
y = "Rank"
) +
theme_minimal()+
theme(
panel.background = element_rect(fill = "#f5f5f5"), # Light gray background
panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.major.y = element_blank(),
legend.position = "none",
plot.title = element_text(size = 12, face = "bold"),
plot.subtitle = element_text(size = 10, face = "italic")
) +
transition_states(year, transition_length = 2, state_length = 1, wrap = FALSE) + # Animate by year
view_follow(fixed_x = FALSE) + scale_y_discrete(limits = rev(levels(factor(dt_top10$rank))))
# Save and embed the animation
anim_save("animation.gif", animate(g, width = 1200, height = 900, fps = 5, units = "px", renderer = gifski_renderer()))
# Embed the GIF in the document
knitr::include_graphics("animation.gif")
Insight: While
the USA leads initially, China consistently dominates EV sales, followed
by the USA, with European countries like Germany and Norway showing
rapid growth, reflecting strong policy support and consumer
adoption.
# Define full forms for powertrains
powertrain_labels <- c(
"BEV" = "Battery Electric Vehicle (BEV)",
"PHEV" = "Plug-in Hybrid Electric Vehicle (PHEV)",
"FCEV" = "Fuel Cell Electric Vehicle (FCEV)"
)
# Filter and summarize data
df_trend <- ev_data %>%
filter(parameter == "EV sales", category == "Historical") %>%
group_by(year, powertrain) %>%
summarise(total_sales = sum(value, na.rm = TRUE)) %>%
mutate(powertrain = factor(powertrain, levels = names(powertrain_labels), labels = powertrain_labels)) # Apply full names
# Create animated line plot
g <- ggplot(df_trend, aes(x = year, y = total_sales, color = powertrain)) +
geom_line(size = 1.2) +
geom_point(size = 2) +
scale_y_continuous(labels = scales::label_number(scale = 1e-6, suffix = "M")) +
scale_x_continuous(breaks = unique(df_trend$year)) +
labs(
title = "Global EV Sales Trend Over Time by Powertrain",
x = "Year",
y = "Total EV Sales (Units)",
color = "Powertrain Type" # Legend title
)+
theme_minimal()+
theme(
panel.background = element_rect(fill = "#f5f5f5"),
panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.major.y = element_blank(),
plot.title = element_text(size = 12, face = "bold"),
plot.subtitle = element_text(size = 10, face = "italic")
) +
transition_reveal(year) # Animates the lines growing over time
# Save the animation as a GIF
anim_save("line_animation.gif", animate(g, width = 1700, height = 800, fps = 5, units = 'px', renderer = gifski_renderer()))
# Embed the GIF in the document
knitr::include_graphics("line_animation.gif")
Insight:
Battery Electric Vehicles (BEVs) dominate global EV sales, with Plug-in
Hybrid Electric Vehicles (PHEVs) showing steady growth, indicating a
shift towards fully electric powertrains. A significant increase is
observed from 2021 onwards.
library(sf)
# Filter for 2022 EV sales share data
ev_2023 <- ev_data %>%
filter(parameter == "EV sales share",
category == "Historical",
mode == "Cars",
powertrain == "EV",
year == 2023)
world_sf <- st_as_sf(maps::map("world", plot = FALSE, fill = TRUE))
# Merge EV sales share with shapefile data
df_map <- merge(world_sf, ev_2023,
by.x = "ID", by.y = "region",
all.x = TRUE)
# Remove countries with NA values for EV sales share
df_map <- df_map %>% filter(!is.na(value))
# Plot EV sales share as text labels on the map
ggplot(df_map) +
geom_sf(aes(fill = value), color = "black") + # No color, only borders
geom_sf_text(aes(label = paste0(round(value, 1), "%")), size = 3, color = "white") +
geom_sf_text(aes(label = ID), size = 3, color = "yellow", nudge_y = 0.5)+
labs(title = "EV cars penetration in Europe by Country (2022)", subtitle = "The map below shows share of EV cars sales for each country in Europe") +
coord_sf(xlim = c(-20, 35), ylim = c(40, 70))+
theme_void()+
theme(panel.background = element_rect(fill = "#f5f5f5"))
Insight: Iceland leads with around 70% of car sales
being electric, driven by aggressive incentives and infrastructure
development.
# Filter data for EV Sales and EV Charging Points
ev_sales_charging_agg <- ev_data %>%
filter(region %in% c("USA", "China", "Europe"),
parameter %in% c("EV sales", "EV charging points"),
category == "Historical",
year == 2023) %>%
group_by(region, parameter) %>%
summarise(total_value = sum(value, na.rm = TRUE)) %>%
ungroup()
# Pivot to create separate columns for EV Sales and EV Charging Points
ev_sales_charging_agg <- ev_sales_charging_agg %>%
pivot_wider(names_from = parameter, values_from = total_value, values_fill = list(total_value = 0))
# Create the plot
fig <- plot_ly(data = ev_sales_charging_agg, x = ~region) %>%
# Add bars for EV Charging Points
add_trace(
y = ~`EV charging points`,
type = 'bar',
name = 'EV Charging Points',
marker = list(color = 'blue')
) %>%
# Add line for EV Sales
add_trace(
y = ~`EV sales`,
type = 'scatter',
mode = 'lines+markers',
name = 'EV Sales',
line = list(color = 'red', width = 3),
marker = list(color = 'red', size = 8)
) %>%
# Layout
layout(
title = list(text = 'EV Sales vs Charging Points (USA, China, Europe)',
font = list(size = 20, face = "bold", color = "black")),
xaxis = list(title = 'Country',
showgrid = FALSE,
titlefont = list(color = "black"),
zeroline = FALSE),
yaxis = list(title = 'Number of Charging Points and EV Sales in Units',
titlefont = list(color = "black"),
zeroline = FALSE),
plot_bgcolor = "#f5f5f5", # Background color
paper_bgcolor = "#f5f5f5", # Outer background color,
margin = list(l = 80, r = 40, t = 80, b = 60) # Adjust margins
)
# Show the plot
fig
Insight: China leads in both EV sales and charging infrastructure, while Europe shows balanced growth. The USA lags in charging points relative to EV sales, highlighting the need for infrastructure investment.