In 2023, a large range of Earthquakes were recorded. In this dataset, the location (long/lat and descriptive), time, magnitude, and more was entered. Through the next visualizations, I will explore the quake types, the locations, the magnitudes, and the season in which the quake occurred.
setwd("C://Users//ashkl//OneDrive//Documents//Loyola//data visualization")
df<- read.csv("earthquakes_2023_global.csv" , na.strings=c(NA, ""))
library(dplyr)
library(ggplot2)
library(leaflet)
library(maps)
library(lubridate)
library(scales)
library(plotly)
Navigate through the below tabs to view some basic statistics of the data.
summary(df)
## time latitude longitude depth
## Length:26642 Min. :-65.850 Min. :-180.00 Min. : -3.37
## Class :character 1st Qu.: -6.415 1st Qu.:-149.61 1st Qu.: 10.00
## Mode :character Median : 18.884 Median : -64.81 Median : 22.00
## Mean : 16.853 Mean : -11.49 Mean : 67.49
## 3rd Qu.: 41.828 3rd Qu.: 126.97 3rd Qu.: 66.83
## Max. : 86.594 Max. : 180.00 Max. :681.24
##
## mag magType nst gap
## Min. :2.600 Length:26642 Min. : 0.00 Min. : 8.0
## 1st Qu.:3.220 Class :character 1st Qu.: 19.00 1st Qu.: 73.0
## Median :4.300 Mode :character Median : 30.00 Median :111.0
## Mean :4.007 Mean : 42.57 Mean :124.9
## 3rd Qu.:4.500 3rd Qu.: 52.00 3rd Qu.:165.0
## Max. :7.800 Max. :423.00 Max. :350.0
## NA's :1415 NA's :1417
## dmin rms net id
## Min. : 0.000 Min. :0.0100 Length:26642 Length:26642
## 1st Qu.: 0.612 1st Qu.:0.4100 Class :character Class :character
## Median : 1.579 Median :0.5900 Mode :character Mode :character
## Mean : 2.693 Mean :0.5816
## 3rd Qu.: 3.172 3rd Qu.:0.7500
## Max. :50.820 Max. :1.8800
## NA's :1866
## updated place type horizontalError
## Length:26642 Length:26642 Length:26642 Min. : 0.000
## Class :character Class :character Class :character 1st Qu.: 4.140
## Mode :character Mode :character Mode :character Median : 7.060
## Mean : 7.017
## 3rd Qu.: 9.730
## Max. :99.000
## NA's :1549
## depthError magError magNst status
## Min. : 0.000 Min. :0.0000 Min. : 0.00 Length:26642
## 1st Qu.: 1.848 1st Qu.:0.0800 1st Qu.: 10.00 Class :character
## Median : 2.019 Median :0.1110 Median : 18.00 Mode :character
## Mean : 4.475 Mean :0.1227 Mean : 33.32
## 3rd Qu.: 6.669 3rd Qu.:0.1500 3rd Qu.: 36.00
## Max. :60.670 Max. :4.4900 Max. :884.00
## NA's :1672 NA's :1577
## locationSource magSource
## Length:26642 Length:26642
## Class :character Class :character
## Mode :character Mode :character
##
##
##
##
str(df)
## 'data.frame': 26642 obs. of 22 variables:
## $ time : chr "2023-01-01T00:49:25.294Z" "2023-01-01T01:41:43.755Z" "2023-01-01T03:29:31.070Z" "2023-01-01T04:09:32.814Z" ...
## $ latitude : num 52.1 7.14 19.16 -4.78 53.4 ...
## $ longitude : num 178.5 126.7 -66.5 102.8 -166.9 ...
## $ depth : num 82.8 79.2 24 63.8 10 ...
## $ mag : num 3.1 4.5 3.93 4.3 3 2.8 4.1 4.1 2.7 4.1 ...
## $ magType : chr "ml" "mb" "md" "mb" ...
## $ nst : num 14 32 23 17 19 19 15 40 30 27 ...
## $ gap : num 139 104 246 187 190 127 87 81 154 119 ...
## $ dmin : num 0.87 1.152 0.848 0.457 0.4 ...
## $ rms : num 0.18 0.47 0.22 0.51 0.31 0.18 0.15 0.32 0.14 0.45 ...
## $ net : chr "us" "us" "pr" "us" ...
## $ id : chr "us7000j5a1" "us7000j3xk" "pr2023001000" "us7000j3xm" ...
## $ updated : chr "2023-03-11T22:51:52.040Z" "2023-03-11T22:51:45.040Z" "2023-03-11T22:51:29.040Z" "2023-03-11T22:51:45.040Z" ...
## $ place : chr "Rat Islands, Aleutian Islands, Alaska" "23 km ESE of Manay, Philippines" "Puerto Rico region" "99 km SSW of Pagar Alam, Indonesia" ...
## $ type : chr "earthquake" "earthquake" "earthquake" "earthquake" ...
## $ horizontalError: num 8.46 5.51 0.91 10.25 1.41 ...
## $ depthError : num 21.21 7.45 15.95 6.58 2 ...
## $ magError : num 0.097 0.083 0.09 0.238 0.085 0.06 0.213 0.095 0.112 0.123 ...
## $ magNst : num 14 43 16 5 18 36 6 34 35 18 ...
## $ status : chr "reviewed" "reviewed" "reviewed" "reviewed" ...
## $ locationSource : chr "us" "us" "pr" "us" ...
## $ magSource : chr "us" "us" "pr" "us" ...
colSums(is.na(df))
## time latitude longitude depth mag
## 0 0 0 0 0
## magType nst gap dmin rms
## 0 1415 1417 1866 0
## net id updated place type
## 0 0 0 1608 0
## horizontalError depthError magError magNst status
## 1549 0 1672 1577 0
## locationSource magSource
## 0 0
eq_cause_count <- df %>%
select(type) %>%
group_by(type) %>%
tally() %>%
data.frame()
eq_cause_count
## type n
## 1 Landslide 2
## 2 earthquake 26428
## 3 explosion 3
## 4 ice quake 26
## 5 landslide 1
## 6 mining explosion 167
## 7 quarry blast 2
## 8 volcanic eruption 13
#initial setup of df
df<- na.omit(df)
df <- subset(df, select = -c(status, updated))
df$country <- gsub(".*, ", "", df$place)
#create df for count of quake types to be used in bar chart
eq_cause_count <- df %>%
select(type) %>%
group_by(type) %>%
tally() %>%
data.frame()
eq_cause_other_pct<- eq_cause_count[-c(1), ]
eq_cause_other_pct$pct <- paste0(round(eq_cause_other_pct$n/sum(eq_cause_other_pct$n) *100, digits =1),"%")
#create dfs for only mining and quarry blast quake types and for volcano types to be used for map
eq_mining <- df[df$type %in% c('mining explosion', 'quarry blast'),]
eq_volcano<- df[df$type %in% c('volcanic eruption'),]
#create df for only earthquakes and one for only non-earth type quakes to be used in dot plot map of all quakes
df$type <- as.factor(df$type)
eq_other<- df[!df$type %in% c('earthquake'),]
earthquake_only <- df[df$type %in% c('earthquake'),]
world_map <- map_data("world")
#create dfs to categorize quake month into seasons with respect to longitude because seasons differ by north/south hemispheres and by equator location then bind them back together
df$time <- as.Date(df$time)
df$season <- month(df$time)
equator_quakes <- df[df$longitude <= 25 & df$longitude >= -25,]
equator_quakes$season <- "Summer"
NHem_quakes <- df[df$longitude > 25,]
NHem_quakes["season"][NHem_quakes["season"] == 1 | NHem_quakes["season"] == 2 | NHem_quakes["season"] == 12] <- "Winter"
NHem_quakes["season"][NHem_quakes["season"] == 3 | NHem_quakes["season"] == 4 | NHem_quakes["season"] == 5] <- "Spring"
NHem_quakes["season"][NHem_quakes["season"] == 6 | NHem_quakes["season"] == 7 | NHem_quakes["season"] == 8] <- "Summer"
NHem_quakes["season"][NHem_quakes["season"] == 9 | NHem_quakes["season"] == 10 | NHem_quakes["season"] == 11] <- "Fall"
SHem_quakes <- df[df$longitude < -25,]
SHem_quakes["season"][SHem_quakes["season"] == 1 | SHem_quakes["season"] == 2 | SHem_quakes["season"] == 12] <- "Summer"
SHem_quakes["season"][SHem_quakes["season"] == 3 | SHem_quakes["season"] == 4 | SHem_quakes["season"] == 5] <- "Fall"
SHem_quakes["season"][SHem_quakes["season"] == 6 | SHem_quakes["season"] == 7 | SHem_quakes["season"] == 8] <- "Winter"
SHem_quakes["season"][SHem_quakes["season"] == 9 | SHem_quakes["season"] == 10 | SHem_quakes["season"] == 11] <- "Spring"
quakes_w_season <- do.call("rbind", list(equator_quakes, NHem_quakes, SHem_quakes))
#get the top 10 countries/states with quakes
place_count <- quakes_w_season %>%
select(season, country) %>%
group_by(country) %>%
tally() %>%
data.frame()
place_count <- place_count[order(place_count$n, decreasing = TRUE), ]
place_count <- place_count[1:10, ]
#get seasons counts of only the top 10
keep<- place_count$country
place_count_season <- subset(quakes_w_season, country %in% keep)
place_count_season <- place_count_season %>%
select(season, country) %>%
group_by(country, season) %>%
tally() %>%
data.frame()
#create season levels for heatmap
mylevels<- c("Spring", "Summer", "Fall", "Winter")
place_count_season$season <- factor(place_count_season$season, levels = mylevels)
#create df for the magnitudes of places in top 10, then factor them
df_magnitudes <- subset(df, country %in% keep)
df_magnitudes <- df_magnitudes %>%
select(country, mag) %>%
mutate(mag_levels = ifelse(mag <= 6, "Minor", ifelse(mag > 6 & mag < 7, "Moderate", ifelse(mag >= 7 & mag < 8, "Major", "Massive")))) %>%
group_by(country, mag_levels) %>%
tally() %>%
group_by(country) %>%
mutate (pct_of_total = round(100*n/sum(n), 1)) %>%
ungroup() %>%
data.frame()
df_magnitudes$mag_levels = factor(df_magnitudes$mag_levels, levels = c("Minor", "Moderate", "Major", "Massive"))
Due to the vast majority of quakes being naturally-occurring earthquakes, included in the below are only the non “Eath” type quakes. As you can see, the majority of these quakes were caused by mining explosions and volcanoes. Were these located in one area?
ggplot(eq_cause_other_pct, aes(x=reorder(type,-n), y=n)) +
geom_histogram(colour = "black", fill="brown", stat="identity") +
labs(title = "Non-normal Earthquakes in 2023", x="Quake Cause",
y="Quake Count") +
geom_text(aes(label=eq_cause_other_pct$pct), vjust=-0.3, size=3.5) +
theme_light() +
theme(plot.title = element_text(hjust=.5, size = 16))
To answer the question of where the volcano and mining quakes happened, navigate through the below tabs to view interactive maps of where each type occurred.
As we can see if we zoom out just a little, all of the volcano quakes were recorded in ocean just North of Northern Mariana Islands.
#Volcanoes
icon.glyphicon <- makeAwesomeIcon(icon = 'fire', markerColor = 'red', iconColor = 'white')
map_volcanoes <- leaflet() %>%
addTiles() %>%
addAwesomeMarkers(lng = eq_volcano$longitude, lat = eq_volcano$latitude,
icon = icon.glyphicon,
popup = paste("Magnitude:", eq_volcano$mag),
label = eq_volcano$place)
map_volcanoes
Surprising, but perhaps not so surprising that all (minus one exception) quakes caused by mining and quarry blasts recorded were located in the United States. This could be due to other countries not classifying the cause, but it could also be that the explosions in other countries were not strong enough to be picked up by a local seismograph.
#quarry/mining blasts
icon.glyphicon <- makeAwesomeIcon(icon = 'star', markerColor = 'red', iconColor = 'white')
map_mining <- leaflet() %>%
addTiles() %>%
addAwesomeMarkers(lng = eq_mining$longitude, lat = eq_mining$latitude,
icon = icon.glyphicon,
popup = paste(eq_mining$place, "| Magnitude:", eq_mining$mag),
label = eq_mining$type
)
map_mining
A dot plot was used to show the location of every quake recorded in 2023. Why a dot plot? Because my poor computer could not load an interactive leaftlet plot and because with a dot plot, I can show where each type of quake occurred.
map_dot<- ggplot() +
coord_fixed() +
xlab("") +
ylab("")+
geom_polygon(data=world_map, aes(x = long, y = lat, group = group),
colour = 'light grey', fill = 'light grey') +
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
panel.background = element_rect(fill = "white", colour = "white"),
axis.line = element_line(colour = "white"),
axis.ticks = element_blank(), axis.text.x = element_blank(),
axis.text.y = element_blank()) +
geom_point(data = earthquake_only, aes(x = longitude, y = latitude), shape = 21, size = 2, fill = 'white', color = 'black') +
geom_point(data = eq_other, aes(x = longitude, y = latitude, color = type, shape = type, fill = type), size = 4) +
scale_shape_manual(values=c(8, 18, 9, 15, 2)) +
labs(title = "Dot Plot with Map of Quakes and Types 2023", x="Latitude", y = "Longitude") +
theme(plot.title = element_text(hjust = .5))
map_dot
This was an interesting find. I created a new dataframe and column for each season (respective of the logitude). The Northern Hemisphere seasons were applied to longitude > 25. Equater season (summer) was applied to longitude <= 25 through longitude >= -25. The Southern Hemisphere seasons were applide to longitude < -25. I found that for most coutries/states, quakes were more common in Winter. Now, in the below heatmap of the top 10 places where quakes occurred, this was not always true, but this was the general trend.
map_heat<- ggplot(place_count_season, aes(x = season, y = country, fill = n))+
geom_tile(color = "black") +
geom_text(aes(label = n)) +
coord_equal(ratio = 1) +
labs(title = "Heatmap: Count of Quakes by Season by Country/State", x = "Season Quake Occurred", y = "State or Country of Quake", fill = "Quake Count") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5)) +
scale_x_discrete(limits = rev(levels(place_count_season$season))) +
scale_fill_continuous(low = "white", high = "blue") +
guides(fill = guide_legend(reverse = TRUE, override.aes = list(colour = "black")))
ggplotly(map_heat, tooltip = c("n", "country", "season")) %>%
style(hoverlabel = list(bgcolor = "white"))
For the top 10 countries where quakes occurred, donut charts were created for the magnitude strength. I have separated the top 10 into separate charts by region. Navigate through the below tabs to view the magnitudes recorded in the United States, Oceania, Asia, and Europe.Magnitude strength is listed as “Minor,” “Moderate,” and “Major.”
US_States <- plot_ly(hole = .7) %>%
layout(title = "Magnitude of Quakes in the United States") %>%
add_trace(data = df_magnitudes[df_magnitudes$country == "Alaska",],
labels = ~mag_levels,
values = ~df_magnitudes[df_magnitudes$country == "Alaska", "n"],
type = "pie",
textposition = "inside",
hovertemplate = "Location: Alaska<br>Magnitude: %{label}<br>Percent: %{percent}<br>Quake Count: %{value}<extra></extra>") %>%
add_trace(data = df_magnitudes[df_magnitudes$country == "CA",],
labels = ~mag_levels,
values = ~df_magnitudes[df_magnitudes$country == "CA", "n"],
type = "pie",
textposition = "inside",
hovertemplate = "Location: California<br>Magnitude: %{label}<br>Percent: %{percent}<br>Quake Count: %{value}<extra></extra>",
domain = list(x = c(0.16, 0.84), y = c(0.16, 0.84))) %>%
add_trace(data = df_magnitudes[df_magnitudes$country == "Puerto Rico",],
labels = ~mag_levels,
values = ~df_magnitudes[df_magnitudes$country == "Puerto Rico", "n"],
type = "pie",
textposition = "inside",
hovertemplate = "Location: Puerto Rico<br>Magnitude: %{label}<br>Percent: %{percent}<br>Quake Count: %{value}<extra></extra>",
domain = list(x = c(0.27, 0.73), y = c(0.27, 0.73)))
US_States
Oceania <- plot_ly(hole = .7) %>%
layout(title = "Magnitude of Quakes in the Oceania") %>%
add_trace(data = df_magnitudes[df_magnitudes$country == "Tonga",],
labels = ~mag_levels,
values = ~df_magnitudes[df_magnitudes$country == "Tonga", "n"],
type = "pie",
textposition = "inside",
hovertemplate = "Location: Tonga<br>Magnitude: %{label}<br>Percent: %{percent}<br>Quake Count: %{value}<extra></extra>") %>%
add_trace(data = df_magnitudes[df_magnitudes$country == "Papua New Guinea",],
labels = ~mag_levels,
values = ~df_magnitudes[df_magnitudes$country == "Papua New Guinea", "n"],
type = "pie",
textposition = "inside",
hovertemplate = "Location: Papua New Guinea<br>Magnitude: %{label}<br>Percent: %{percent}<br>Quake Count: %{value}<extra></extra>",
domain = list(x = c(0.16, 0.84), y = c(0.16, 0.84)))
Oceania
Asia <- plot_ly(hole = .7) %>%
layout(title = "Magnitude of Quakes in Asia") %>%
add_trace(data = df_magnitudes[df_magnitudes$country == "Indonesia",],
labels = ~mag_levels,
values = ~df_magnitudes[df_magnitudes$country == "Indonesia", "n"],
type = "pie",
textposition = "inside",
hovertemplate = "Location: Indonesia<br>Magnitude: %{label}<br>Percent: %{percent}<br>Quake Count: %{value}<extra></extra>") %>%
add_trace(data = df_magnitudes[df_magnitudes$country == "Japan",],
labels = ~mag_levels,
values = ~df_magnitudes[df_magnitudes$country == "Japan", "n"],
type = "pie",
textposition = "inside",
hovertemplate = "Location: Japan<br>Magnitude: %{label}<br>Percent: %{percent}<br>Quake Count: %{value}<extra></extra>",
domain = list(x = c(0.16, 0.84), y = c(0.16, 0.84))) %>%
add_trace(data = df_magnitudes[df_magnitudes$country == "Japan region",],
labels = ~mag_levels,
values = ~df_magnitudes[df_magnitudes$country == "Japan region", "n"],
type = "pie",
textposition = "inside",
hovertemplate = "Location: Japan Region<br>Magnitude: %{label}<br>Percent: %{percent}<br>Quake Count: %{value}<extra></extra>",
domain = list(x = c(0.27, 0.73), y = c(0.27, 0.73))) %>%
add_trace(data = df_magnitudes[df_magnitudes$country == "Philippines",],
labels = ~mag_levels,
values = ~df_magnitudes[df_magnitudes$country == "Philippines", "n"],
type = "pie",
textposition = "inside",
hovertemplate = "Location: Philippines<br>Magnitude: %{label}<br>Percent: %{percent}<br>Quake Count: %{value}<extra></extra>",
domain = list(x = c(0.345, 0.655), y = c(0.345, 0.655)))
Asia
Europe <- plot_ly(hole = .7) %>%
layout(title = "Magnitude of Quakes in Europe") %>%
add_trace(data = df_magnitudes[df_magnitudes$country == "Turkey",],
labels = ~mag_levels,
values = ~df_magnitudes[df_magnitudes$country == "Turkey", "n"],
type = "pie",
textposition = "inside",
hovertemplate = "Location: Turkey<br>Magnitude: %{label}<br>Percent: %{percent}<br>Quake Count: %{value}<extra></extra>")
Europe
Earthquakes happen all over the world every day. While more uncommon, other quake types such as mining explosions, volcanoes, and ice quakes occur. Most, if not all, natural earthquakes happen around the earth’s technonic plates. As a general rule, more earthquakes occur in the cold winter months; this could be due the natural expansion and contraction of heating and cooling, but more research should be done to confirm this. The vast majority of earthquakes that occurred in 2023 were minor quakes with a magnitude <= 6 on the Richter scale.