Instructions
What Is The Effect Of The Earth’s Temperature on Cyclonic Storms?
Historic data indicates that the occurrence and intensity of cyclonic storms (Hurricanes, Typhoons and Tornados) increases with the increased earth temperature. For this assignment you will need to tell this story to a non-technical audience (eg: a high-school earth science class).
Notes:
Source historic data for a period of at least 25 years on a measure of the earth’s temperature.
Source data on the occurrence and intensity of hurricanes, typhoons and tornados for the same historic period.
Perform the data analysis to establish the correlations between earth temperature and storm occurrence and intensity.
Tell the story of this data and your analysis using data visualizations and other illustrations (eg: pictures of storm damage) in a presentation that will be accessible to a high-school earth science class.
Introduction
As global temperatures continue to rise, scientists have observed notable shifts in the behavior and strength of cyclonic storms.
This analysis explores how Earth’s temperature trends influence storm frequency and intensity using real-world climate and storm data.
The goal is to uncover whether warming patterns correlate with stronger or more frequent cyclones.
Load Temperature Data
This section loads the two datasets used in the analysis and prepares them so they can be compared year by year.
Global Temperature Anomalies: Annual temperature measurements that show how much warmer or cooler each year was compared to long-term averages.
Worldwide Cyclone Records (IBTrACS): A global archive of hurricanes, typhoons, and cyclones. It includes each storm’s wind speed, movement, location, and how close it came to land.
The code below reads both datasets, cleans the fields we need, and connects them using the year. Basin codes in the storm data are also matched with their full names so the regions are easier to understand when we analyze them later.
# Read the storm and temperature data | Clean metadata
temperature_data <- read.csv("temperature_data.csv", skip = 4, header = TRUE)
# Rename columns for clarity
colnames(temperature_data) <- c("Year", "Anomaly")
# Convert columns to numeric
temperature_data <- temperature_data %>%
mutate(
Year = as.numeric(Year),
Anomaly = as.numeric(Anomaly)
) %>%
filter(!is.na(Year))
kable(
head(temperature_data),
caption = "View Temperature Data"
)| Year | Anomaly |
|---|---|
| 1997 | 0.42 |
| 1998 | 0.67 |
| 1999 | 0.44 |
| 2000 | 0.45 |
| 2001 | 0.48 |
| 2002 | 0.63 |
storm_data_world <- read.csv("ibtracs.ALL.list.v04r01.csv")
#, nrows = 100000)
if ("Season" %in% names(storm_data_world)) {
storm_data_world <- storm_data_world %>% rename(SEASON = Season)
} else if ("year" %in% names(storm_data_world)) {
storm_data_world <- storm_data_world %>% rename(SEASON = year)
} else if ("YEAR" %in% names(storm_data_world)) {
storm_data_world <- storm_data_world %>% rename(SEASON = YEAR)
}
# Convert SEASON to numeric
storm_data_world <- storm_data_world %>%
mutate(SEASON = as.numeric(SEASON))
# Ensure both datasets have numeric year columns
storm_data_world <- storm_data_world %>%
inner_join(temperature_data, by = c("SEASON" = "Year")) %>%
rename(year = SEASON)
basin_mapping <- data.frame(
BASIN = c("NA", "EP", "WP", "SI", "AU", "NI", "SA"),
BASIN_NAME = c(
"North Atlantic", "Eastern Pacific", "Western Pacific",
"South Indian", "Australia", "Northern Indian", "South Atlantic"
)
)
storm_data_world <- storm_data_world %>%
left_join(basin_mapping, by = "BASIN")
#glimpse(storm_data_world)
#head(storm_data_world)Create a data frame for max wind and speed for each storm
The table below shows the maximum recorded wind speed and storm speed for each storm. I grouped the data by SID and calculated the highest value of USA_WIND and STORM_SPEED while accounting for missing values.
# Ensure USA_WIND and STORM_SPEED are numeric
storm_data_world <- storm_data_world %>%
mutate(
USA_WIND = as.numeric(USA_WIND),
STORM_SPEED = as.numeric(STORM_SPEED)
)
# Group by SID and summarize to find the maximum values, handling missing data
max_wind_data <- storm_data_world %>%
group_by(SID) %>%
summarise(
Max_Wind = ifelse(all(is.na(USA_WIND)), NA, max(USA_WIND, na.rm = TRUE)),
Max_Storm_Speed = ifelse(all(is.na(STORM_SPEED)), NA, max(STORM_SPEED, na.rm = TRUE)),
.groups = "drop"
)
# Display the first few rows of max_wind_data
#head(max_wind_data)
kable(
head(max_wind_data),
caption = "Display the first few rows of max_wind_data"
)| SID | Max_Wind | Max_Storm_Speed |
|---|---|---|
| 1996190S07096 | 35 | 9 |
| 1996228S05084 | 45 | 10 |
| 1996247S09084 | 40 | 10 |
| 1996289S05093 | 65 | 20 |
| 1996302S07095 | 125 | 16 |
| 1996324S04164 | 50 | 17 |
Visualizing Global Temperature Anomalies Over Time
This code visualizes the trend in global temperature anomalies, combining raw data and a smoothed line to highlight long-term climatic changes. The gray line represents yearly anomalies, while the red line smooths the data to reveal underlying patterns.
# Add the anomaly data (ensuring there are no duplicates)
anomaly_data <- storm_data_world %>%
select(year, Anomaly) %>%
distinct()
# Smooth the temperature anomaly
anomaly_data <- anomaly_data %>%
mutate(
Smoothed_Anomaly = rollmean(Anomaly, k = 10, fill = NA, align = "center")
)ggplot(anomaly_data, aes(x = year)) +
geom_line(aes(y = Anomaly), color = "Blue", size = 0.8, alpha = 0.7) +
geom_line(aes(y = Smoothed_Anomaly), color = "red", size = 0.7) +
labs(
title = "Rising Global Temperature Anomalies Over Time",
subtitle = "Observed anomalies with a smoothed trend line",
x = "Year",
y = "Temperature Anomaly (°C)"
) +
theme_minimal(base_size = 14) +
theme(
legend.position = "none",
plot.title = element_text(face = "bold", size = 19),
plot.subtitle = element_text(size = 15),
axis.text.x = element_text(angle = 45, hjust = 1)
)The chart shows that global temperature anomalies have been trending upward over time. While individual years fluctuate, the smoothed line makes the long-term pattern clear. Recent decades show consistently higher anomalies compared to the earlier part of the record, which signals a steady rise in global temperatures. This supports the broader evidence of ongoing climate warming.
Impact of Temperature Anomalies on Storm Speed and Intensity Over Time
This visualization explores how rising global temperatures have influenced storm behavior over the years. The red line shows smoothed temperature anomalies (C), while the blue and green lines represent scaled storm speed and intensity, respectively. As temperature anomalies increase, both storm speed and intensity exhibit upward trends—suggesting that warmer global conditions may be fueling stronger and faster cyclonic storms. The primary y-axis measures storm metrics, and the secondary y-axis represents temperature anomalies.
# Extract maximum storm speed and USA wind speed for each SID and year
storm_data <- storm_data_world %>%
filter(!is.na(STORM_SPEED) & !is.na(USA_WIND)) %>%
mutate(
STORM_SPEED = as.numeric(STORM_SPEED),
USA_WIND = as.numeric(USA_WIND)
) %>%
group_by(SID, year) %>%
summarise(
Max_Storm_Speed = max(STORM_SPEED, na.rm = TRUE),
Max_USA_Wind = max(USA_WIND, na.rm = TRUE),
.groups = "drop"
)
# Aggregate by year
yearly_data <- storm_data %>%
group_by(year) %>%
summarise(
Max_Storm_Speed = max(Max_Storm_Speed, na.rm = TRUE),
Max_USA_Wind = max(Max_USA_Wind, na.rm = TRUE),
.groups = "drop"
)
# Add temperature anomaly data
anomaly_data <- storm_data_world %>%
select(year, Anomaly) %>%
distinct()
combined_data <- yearly_data %>%
left_join(anomaly_data, by = "year") %>%
filter(!is.na(Anomaly)) # Remove years with missing anomaly data
# Scale and smooth the values
combined_data <- combined_data %>%
mutate(
Scaled_Storm_Speed = scale(Max_Storm_Speed),
Scaled_USA_Wind = scale(Max_USA_Wind),
Scaled_Anomaly = scale(Anomaly),
Smoothed_Storm_Speed = rollmean(Scaled_Storm_Speed, k = 10, fill = NA, align = "center"),
Smoothed_USA_Wind = rollmean(Scaled_USA_Wind, k = 10, fill = NA, align = "center"),
Smoothed_Anomaly = rollmean(Scaled_Anomaly, k = 10, fill = NA, align = "center")
)
# Define manual y-tick labels for primary axis (Max Storm Speed)
storm_speed_ticks <- pretty(combined_data$Max_Storm_Speed) # Generate pretty tick values for Max Storm Speed
scaled_storm_speed_ticks <- (storm_speed_ticks - mean(combined_data$Max_Storm_Speed)) / sd(combined_data$Max_Storm_Speed) # Scale the tick values# Plot with secondary y-axis and manual tick replacements
ggplot(combined_data, aes(x = year)) +
geom_line(aes(y = Smoothed_Storm_Speed, color = "Storm Speed"), size = 0.5) +
geom_line(aes(y = Smoothed_USA_Wind, color = "Storm Intensity"), size = 0.5) +
geom_line(aes(y = Smoothed_Anomaly, color = "Temperature Anomaly"), size = 0.5) +
scale_y_continuous(
name = "Storm Speed and Intensity (km/h)",
breaks = scaled_storm_speed_ticks, # Use scaled Max Storm Speed values as breaks
labels = storm_speed_ticks, # Display actual Max Storm Speed values as labels
sec.axis = sec_axis(
~ . * sd(combined_data$Anomaly) + mean(combined_data$Anomaly), # Scale back anomaly to actual values
name = "Temperature Anomaly (°C)"
)
) +
scale_color_manual(
values = c(
"Storm Speed" = "blue",
"Storm Intensity" = "green",
"Temperature Anomaly" = "red"
),
name = "Metrics"
) +
labs(
title = "Impact of Temperature Anomalies on Storm Speed and Storm Intensitty Over Time",
x = "Year"
) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 14, hjust = 0.5),
axis.title = element_text(face = "bold"),
axis.text.x = element_text(angle = 45, hjust = 1),
legend.title = element_text(face = "bold"),
legend.position = "top"
)The visualization reveals a clear upward association between rising global temperature anomalies and storm behavior over time. As temperature anomalies increase, both the average storm speed and storm intensity tend to rise as well. This pattern suggests that warmer global and oceanic conditions may be contributing to stronger and faster cyclonic storms, aligning with scientific observations that climate change amplifies storm dynamics and energy.
Relationship Between Temperature Anomaly and Annual Maximum Wind Speed Over Time
This visualization illustrates how rising temperature anomalies correspond with changes in maximum annual wind speeds. The blue curve shows the smoothed annual maximum wind speed (in knots), while the red curve represents smoothed temperature anomalies (in °C). The primary y-axis displays wind speeds, and the secondary y-axis shows temperature anomalies, adjusted to reflect actual values on the scale. Together, these trends suggest that as global temperatures increase, cyclonic storms tend to reach higher maximum wind speeds, highlighting the potential impact of global warming on storm intensity over time.
# Extract maximum wind speed for each SID and year
max_wind_per_year <- storm_data_world %>%
filter(!is.na(USA_WIND)) %>%
mutate(USA_WIND = as.numeric(USA_WIND)) %>%
group_by(SID, year) %>%
summarise(Max_Wind = max(USA_WIND, na.rm = TRUE), .groups = "drop") %>%
group_by(year) %>%
summarise(Annual_Max_Wind = max(Max_Wind, na.rm = TRUE), .groups = "drop")
# Add the anomaly data (ensuring there are no duplicates)
anomaly_data <- storm_data_world %>%
select(year, Anomaly) %>%
distinct()
# Combine wind speed and anomaly data
combined_data <- max_wind_per_year %>%
left_join(anomaly_data, by = "year") %>%
filter(!is.na(Anomaly)) # Remove years with missing anomaly data
# Scale and center the values
combined_data <- combined_data %>%
mutate(
Scaled_Max_Wind = scale(Annual_Max_Wind),
Scaled_Anomaly = scale(Anomaly),
Smoothed_Max_Wind = rollmean(Scaled_Max_Wind, k = 10, fill = NA, align = "center"),
Smoothed_Anomaly = rollmean(Scaled_Anomaly, k = 10, fill = NA, align = "center")
)
# Define manual y-tick labels for primary axis (Max Wind Speed)
max_wind_ticks <- pretty(combined_data$Annual_Max_Wind) # Generate pretty tick values for Max Wind Speed
scaled_max_wind_ticks <- (max_wind_ticks - mean(combined_data$Annual_Max_Wind)) / sd(combined_data$Annual_Max_Wind) # Scale the tick values# Plot with secondary y-axis and manual tick replacements
ggplot(combined_data, aes(x = year)) +
geom_line(aes(y = Smoothed_Max_Wind, color = "Max Wind Speed (Smoothed)"), size = 0.5) +
geom_line(aes(y = Smoothed_Anomaly, color = "Temperature Anomaly (Smoothed)"), size = 0.5) +
scale_y_continuous(
name = "Annual Maximum Wind Speed (knots)",
breaks = scaled_max_wind_ticks, # Use scaled Max Wind values as breaks
labels = max_wind_ticks, # Display actual Max Wind Speed values as labels
sec.axis = sec_axis(
~ . * sd(combined_data$Anomaly) + mean(combined_data$Anomaly), # Scale back anomaly to actual values
name = "Temperature Anomaly (°C)"
)
) +
scale_color_manual(
values = c(
"Max Wind Speed (Smoothed)" = "blue",
"Temperature Anomaly (Smoothed)" = "red"
),
name = expression(bold("Metric"))
) +
labs(
title = expression(bold("Relationship Between Temperature Anomaly and Annual Maximum Wind Speed Over Time")),
x = "Year"
) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 14, hjust = 0.5),
axis.title = element_text(face = "bold"),
axis.text.x = element_text(angle = 45, hjust = 1),
legend.title = element_text(face = "bold"),
legend.position = "top"
)Number of Storms Making Landfall Over the Years
This visualization depicts the annual trend in storms making landfall, based on records where landfall was identified directly or inferred from proximity to coastlines. The blue line shows the yearly count of landfalling storms, while the red smoothed line reveals the long-term trend. Overall, the data suggest a gradual increase in landfalling storms over time, highlighting growing risks for coastal regions and communities.
# Filter for storms that made landfall
storms_with_landfall <- storm_data_world %>%
filter(
(LANDFALL == 0 & DIST2LAND == 0) |
grepl("L", USA_RECORD)
) %>%
distinct(SID, year)
# Count the number of storms that made landfall per year
landfall_count_per_year <- storms_with_landfall %>%
group_by(year) %>%
summarise(Landfall_Count = n(), .groups = "drop")
ggplot(landfall_count_per_year, aes(x = year, y = Landfall_Count)) +
geom_line(color = "blue", size = 0.7) +
geom_smooth(method = "loess", color = "red", size = 0.5) + # Smoothed trend line
labs(
title = "Number of Storms Making Landfall Over the Years",
subtitle = "Trends in tropical storms, hurricanes, and major hurricanes making landfall annually",
x = "Year",
y = "Number of Storms"
) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 15, hjust = 0.5),
plot.subtitle = element_text(size = 12, hjust = 0.5, color = "gray30"),
axis.title = element_text(face = "bold"),
axis.text.x = element_text(angle = 45, hjust = 1),
legend.title = element_text(face = "bold"),
legend.position = "top",
panel.grid.major = element_line(color = "gray90")
)The number of storms making landfall has gradually increased over the years. This trend, seen across storm types, suggests that warmer ocean conditions may be contributing to more frequent and intense coastal storms.
Destructive Potential Index (DPI) for storms
The DPI measures the potential destructiveness of storms by combining storm speed, wind intensity, and proximity to land. It allows us to track yearly trends in storm destructiveness.
Formula:
The DPI formula is defined as:
DPI = (0.3 × Normalized Storm Speed + 0.7 × Normalized Wind Speed) × Land Proximity Factor
Explanation of Terms:
Weights:
Conclusion
This analysis shows how the Total Destructive Potential Index (DPI) has varied over time, reflecting the cumulative destructive potential of storms each year. The inclusion of storm speed, wind speed, and land proximity provides a comprehensive measure of destructiveness.
Analysis of the plot
This visualization demonstrates the Total Destructive Potential Index (DPI) aggregated yearly for storms categorized from 1 to 5 in the dataset. A key observation from the plot is:
Upward Trend: The red dashed trend line suggests an overall increase in the total DPI over time. This indicates that the cumulative destructive potential of storms has generally risen since the mid-19th century.
Fluctuations: While the DPI shows year-to-year variability, several spikes highlight years with highly destructive storms. These spikes could correspond to major storm events or seasons with multiple impactful storms.
Recent Decades: In the latter half of the 20th century and early 21st century, the DPI appears to have reached higher peaks compared to earlier periods, aligning with the increase in storm intensity and frequency reported in recent studies.
This analysis highlights the importance of considering both natural variability and potential climate-related factors influencing storm behavior over time.
# Normalize function
normalize <- function(x) {
return((x - min(x, na.rm = TRUE)) / (max(x, na.rm = TRUE) - min(x, na.rm = TRUE)))
}
# Calculate DPI for each storm
storm_dpi <- storm_data_world %>%
filter(!is.na(STORM_SPEED) & !is.na(USA_WIND) & !is.na(DIST2LAND)) %>%
mutate(
STORM_SPEED = as.numeric(STORM_SPEED),
USA_WIND = as.numeric(USA_WIND),
DIST2LAND = as.numeric(DIST2LAND),
Norm_Storm_Speed = normalize(STORM_SPEED),
Norm_Wind_Speed = normalize(USA_WIND),
Land_Proximity_Factor = 1 / (DIST2LAND + 1),
DPI = (0.3 * Norm_Storm_Speed) + (0.7 * Norm_Wind_Speed) * Land_Proximity_Factor
)
# Aggregate DPI by year
annual_dpi <- storm_dpi %>%
group_by(year) %>%
summarise(
Total_DPI = sum(DPI, na.rm = TRUE),
.groups = "drop"
)
# Add anomaly data
anomaly_data <- storm_data_world %>%
select(year, Anomaly) %>%
distinct()
# Combine DPI and anomaly data
combined_dpi_data <- annual_dpi %>%
left_join(anomaly_data, by = "year") %>%
filter(!is.na(Anomaly))
# Scale and smooth the values
combined_dpi_data <- combined_dpi_data %>%
mutate(
Scaled_DPI = scale(Total_DPI),
Scaled_Anomaly = scale(Anomaly),
Smoothed_DPI = rollmean(Scaled_DPI, k = 10, fill = NA, align = "center"),
Smoothed_Anomaly = rollmean(Scaled_Anomaly, k = 10, fill = NA, align = "center")
)
# Define manual y-tick labels for primary axis (DPI)
dpi_ticks <- pretty(combined_dpi_data$Total_DPI) # Generate pretty tick values for DPI
scaled_dpi_ticks <- (dpi_ticks - mean(combined_dpi_data$Total_DPI)) / sd(combined_dpi_data$Total_DPI) # Scale the tick values
# Plot with secondary y-axis and manual tick replacements
ggplot(combined_dpi_data, aes(x = year)) +
geom_line(aes(y = Smoothed_DPI, color = "DPI (Smoothed)"), size = 0.5) +
geom_line(aes(y = Smoothed_Anomaly, color = "Temperature Anomaly (Smoothed)"), size = 0.5) +
scale_y_continuous(
name = "Total DPI",
breaks = scaled_dpi_ticks, # Use scaled DPI values as breaks
labels = dpi_ticks, # Display actual DPI values as labels
sec.axis = sec_axis(
~ . * sd(combined_dpi_data$Anomaly) + mean(combined_dpi_data$Anomaly), # Scale back anomaly to actual values
name = "Temperature Anomaly (°C)"
)
) +
scale_color_manual(
values = c("DPI (Smoothed)" = "purple", "Temperature Anomaly (Smoothed)" = "red"),
name = "Metric"
) +
labs(
title = "Temperature Anomaly and Annual DPI Over Time",
subtitle = "Tracking the Cumulative Destructive Potential of Storms",
x = "Year"
) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "top",
plot.title = element_text(face = "bold", size = 14),
plot.subtitle = element_text(face = "bold", size = 12)
)Temperature Anomaly vs Cyclone Frequency
This scatterplot examines the relationship between global temperature anomalies and cyclone frequency. Each black point represents a year’s average temperature anomaly plotted against the total number of cyclones that occurred during that year. The red line represents a linear regression trend, illustrating the relationship between the two variables. This visualization highlights how changes in Earth’s temperature anomalies may influence the frequency of cyclonic storms.
# Group by year to calculate cyclone frequency
cyclone_frequency <- storm_data_world %>%
group_by(year) %>%
summarise(
Avg_Temperature_Anomaly = mean(Anomaly, na.rm = TRUE),
Cyclone_Frequency = n()
)
# Plot
ggplot(cyclone_frequency, aes(x = Avg_Temperature_Anomaly, y = Cyclone_Frequency)) +
geom_point(color = "blue", alpha = 0.6, size = 2) + # Slightly larger points
geom_smooth(method = "lm", color = "red", se = FALSE, size = 0.8) +
labs(
title = "Temperature Anomaly vs Cyclone Frequency",
subtitle = "Relationship between global temperature anomalies and annual cyclone occurrences",
x = "Temperature Anomaly (°C)",
y = "Cyclone Frequency"
) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 16),
plot.subtitle = element_text(face = "bold", size = 12, color = "gray30"),
axis.title = element_text(face = "bold"),
axis.text = element_text(color = "black"),
panel.grid.major = element_line(color = "gray90"),
panel.grid.minor = element_blank()
)This scatterplot indicates a positive relationship between global temperature anomalies and cyclone frequency. Years with higher temperature anomalies tend to experience more cyclones, as highlighted by the upward-sloping regression line. While there is year-to-year variability, the overall trend suggests that rising global temperatures may contribute to increased cyclone activity, emphasizing the potential influence of climate change on storm frequency.
Temperature Anomaly and Cyclone Frequency Over Time
This line graph compares smoothed trends in cyclone frequency and temperature anomalies over the years. The blue line represents the smoothed cyclone frequency, while the red line shows the smoothed temperature anomaly. The primary y-axis represents cyclone frequency with its original values manually labeled, while the secondary y-axis depicts temperature anomalies in degrees Celsius. This visualization illustrates the correlation between rising global temperatures and changes in cyclone activity.
# Calculate yearly cyclone frequency
cyclone_frequency <- storm_data_world %>%
group_by(year) %>%
summarise(Cyclone_Frequency = n(), .groups = "drop")
# Add temperature anomaly data
anomaly_data <- storm_data_world %>%
select(year, Anomaly) %>%
distinct()
# Combine cyclone frequency and anomaly data
combined_data <- cyclone_frequency %>%
left_join(anomaly_data, by = "year") %>%
filter(!is.na(Anomaly)) # Remove missing anomaly data
# Create scaled columns for analysis
combined_data <- combined_data %>%
mutate(
Scaled_Frequency = scale(Cyclone_Frequency),
Scaled_Anomaly = scale(Anomaly),
Smoothed_Frequency = rollmean(Scaled_Frequency, k = 10, fill = NA, align = "center"),
Smoothed_Anomaly = rollmean(Scaled_Anomaly, k = 10, fill = NA, align = "center")
)
# Define manual y-tick labels for the primary axis
frequency_ticks <- pretty(combined_data$Cyclone_Frequency) # Get pretty tick values for cyclone frequency
scaled_frequency_ticks <- scale(frequency_ticks) # Scale the frequency ticks to match the plot
scaled_frequency_ticks <- (frequency_ticks - mean(combined_data$Cyclone_Frequency)) /
sd(combined_data$Cyclone_Frequency)
# Plot with manual ticks and bold formatting
ggplot(combined_data, aes(x = year)) +
geom_line(aes(y = Smoothed_Frequency, color = "Cyclone Frequency (Smoothed)"), size = 0.5) +
geom_line(aes(y = Smoothed_Anomaly, color = "Temperature Anomaly (Smoothed)"), size = 0.5) +
scale_y_continuous(
name = "Cyclone Frequency",
breaks = scaled_frequency_ticks, # Scaled breaks
labels = frequency_ticks, # Original values as labels
sec.axis = sec_axis(
~ . * sd(combined_data$Anomaly) + mean(combined_data$Anomaly),
name = "Temperature Anomaly (°C)"
)
) +
scale_color_manual(
values = c("Cyclone Frequency (Smoothed)" = "blue", "Temperature Anomaly (Smoothed)" = "red"),
name = "Metric"
) +
labs(
title = "Temperature Anomaly and Cyclone Frequency Over Time",
subtitle = "Smoothed trends of cyclone frequency and global temperature anomalies",
x = "Year"
) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 16),
plot.subtitle = element_text(face = "bold", size = 12),
axis.title.x = element_text(face = "bold"),
axis.title.y = element_text(face = "bold"),
axis.text.x = element_text(angle = 45, hjust = 1),
legend.title = element_text(face = "bold"),
legend.position = "top"
)Rising Earth’s Temperature and Its Impact on Cyclonic Storm Metrics
This visualization illustrates the relationship between rising global temperatures and the increasing frequency, intensity, speed, and overall destructiveness of cyclonic storms over time. The heatmap highlights how temperature anomalies correlate with these growing storm metrics, underscoring the broader impacts of climate change on tropical cyclone behavior.
library(tidyr)
# Define the DPI formula and add it to the storm_data_world dataset
storm_data_world <- storm_data_world %>%
filter(!is.na(STORM_SPEED) & !is.na(USA_WIND) & !is.na(DIST2LAND)) %>% # Filter valid data
mutate(
STORM_SPEED = as.numeric(STORM_SPEED),
USA_WIND = as.numeric(USA_WIND),
DIST2LAND = as.numeric(DIST2LAND),
Norm_Storm_Speed = (STORM_SPEED - min(STORM_SPEED, na.rm = TRUE)) / (max(STORM_SPEED, na.rm = TRUE) - min(STORM_SPEED, na.rm = TRUE)),
Norm_Wind_Speed = (USA_WIND - min(USA_WIND, na.rm = TRUE)) / (max(USA_WIND, na.rm = TRUE) - min(USA_WIND, na.rm = TRUE)), # Normalize wind speed
Land_Proximity_Factor = 1 / (DIST2LAND + 1), # Closer storms get higher weight
DPI = (0.3 * Norm_Storm_Speed) + (0.7 * Norm_Wind_Speed * Land_Proximity_Factor) # Calculate DPI
)# Aggregate the data by year and calculate maximum values for each metric
max_metrics_per_year <- storm_data_world %>%
group_by(year) %>%
summarise(
Max_DPI = max(DPI, na.rm = TRUE),
Max_Storm_Frequency = n_distinct(SID),
Max_Storm_Speed = max(STORM_SPEED, na.rm = TRUE),
Max_Wind_Speed = max(USA_WIND, na.rm = TRUE),
Avg_Anomaly = mean(Anomaly, na.rm = TRUE), # Calculate average anomaly for the legend
.groups = "drop"
)
# Scale the data for all metrics
scaled_data <- max_metrics_per_year %>%
mutate(
Scaled_DPI = scale(Max_DPI),
Scaled_Storm_Frequency = scale(Max_Storm_Frequency),
Scaled_Storm_Speed = scale(Max_Storm_Speed),
Scaled_Wind_Speed = scale(Max_Wind_Speed)
) %>%
select(year, Scaled_DPI, Scaled_Storm_Frequency, Scaled_Storm_Speed, Scaled_Wind_Speed, Avg_Anomaly) %>%
pivot_longer(
cols = starts_with("Scaled"),
names_to = "Metric",
values_to = "Value"
)
# Rename metrics for better readability in the plot
scaled_data$Metric <- recode(scaled_data$Metric,
"Scaled_DPI" = "DPI",
"Scaled_Storm_Frequency" = "Storm Frequency",
"Scaled_Storm_Speed" = "Storm Speed",
"Scaled_Wind_Speed" = "Wind Speed")ggplot(scaled_data, aes(x = Metric, y = year, fill = Value)) +
geom_tile(color = "white") + # Borders for clarity
scale_fill_gradient2(
low = "blue", mid = "white", high = "red",
midpoint = 0, name = "Scaled Value"
) +
labs(
title = "Rising Global Temperatures and Cyclonic Storm Metrics",
subtitle = "Heatmap shows the increase in frequency, intensity, speed, and destructiveness over time",
x = "Storm Metrics",
y = "Year"
) +
theme_minimal(base_size = 12) +
theme(
axis.text.x = element_text(angle = 45, hjust = 1, face = "bold"),
axis.title = element_text(face = "bold"),
plot.title = element_text(size = 16, face = "bold"),
plot.subtitle = element_text(size = 12, face = "italic"),
panel.grid = element_line(color = "gray90")
)This heatmap illustrates the strong relationship between rising global temperatures and key cyclonic storm metrics—frequency, intensity, speed, and destructiveness—over time. Warmer years (red shades) correspond to higher scaled values of storm metrics, indicating that as Earth’s temperature anomalies increase, storms tend to become more frequent, faster, stronger, and more destructive. The visualization emphasizes the cumulative impact of climate change on cyclonic activity and highlights the importance of monitoring these trends for disaster preparedness and mitigation strategies.
Conclusion
The data shows that as Earth’s temperature rises, cyclonic storms like hurricanes, typhoons, and cyclones are becoming stronger, faster, more frequent, and more destructive.
Storms are more intense: Higher wind speeds and faster-moving storms happen in warmer years.
More storms hit land: Coastal areas face more frequent storm landfalls.
Overall destructiveness is increasing: The combination of storm speed, wind, and closeness to land means storms today can cause more damage than in the past.
This clearly shows that climate change is making storms more dangerous, highlighting the need for awareness, preparedness, and action to protect communities.