library(tidyverse)  
library(ggplot2)
library(gganimate)
library(plotly)
library(data.table)
library(sf)
library(gifski)
library(dplyr)

Top 10 Countries by EV Sales Over Time

# 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.

Global EV Sales Trend by Powertrain

# 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.

EV Penetration in Europe by Country (2022)

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.

EV Sales vs Charging Points (USA, China, Europe)

# 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.

EV vs Non-EV Sales Share (World)

# Filter dataset
ev_sales_data <- ev_data %>%
  filter(region == "World", mode == "Cars", powertrain == "EV", parameter == "EV sales share") %>%
  select(year, value)

# Create non-EV sales share
ev_sales_data <- ev_sales_data %>%
  mutate(`Non-EV sales share` = 100 - value)

# Convert to long format for Plotly
ev_sales_long <- ev_sales_data %>%
  pivot_longer(cols = c(value, `Non-EV sales share`), names_to = "Sales Type", values_to = "Share") %>%
  mutate(`Sales Type` = ifelse(`Sales Type` == "value", "EV Sales Share", "Non-EV Sales Share"))

# Create animated pie chart
fig <- plot_ly(
  data = ev_sales_long,
  labels = ~`Sales Type`,
  values = ~Share,
  type = 'pie',
  textinfo = 'label+percent',
  hoverinfo = 'label+percent',
  frame = ~year,
  marker = list(colors = c('green', 'lightgrey'))  # EV share in green, Non-EV in grey
) %>%
  layout(
    title = list(
      text = "EV vs Non-EV Sales Share (World)",
      font = list(size = 20, family = "Arial", color = "black") # Bold title
    ),
    paper_bgcolor = "#f5f5f5",  # Background color
    plot_bgcolor = "#f5f5f5",   # Background color inside plot
    showlegend = TRUE,
    margin = list(l = 50, r = 50, t = 80, b = 50))  # Adjust margins

# Show plot
fig

Insight: EVs are gaining market share globally, but non-EVs still dominate, underscoring the need for continued investment in EV adoption and infrastructure.