La informacion que usaron para este Kaggle se tomo del USGS(U.S Geological Survey). Este contiene datos e informacion cientifica verificada sobre sucesos geologicos que conciernen a las personas.
El Servicio Geologico Estadounidense es el encargado de monitorear y reportar acerca de terremotos, sus causas, impactos y peligros que estos generan. Tambien envia notificaciones, alertas y demas servicios acerca de terremotos antes que estos ocurran. Se puede encontrar mas informacion en el siguiente link:
El autor del Kaggle, cuando extraia la informacion de la pagina, descubrio que no todos los terremotos que se dan se presentan por procesos naturales. Algunos se presentan por actividades humanas como explociones en minas o explociones quimicas. En el periodo de febrero-Marzo de 2019 se dieron mas de 8500 terremotos en el mundo, de los cuales solo el 2% se dieron por actividades en la superrficie.
Al final del trabajo se intento predecir los terremotos y otros tipos de temblores. Asi que el primer paso a seguir es decargar la librerias de informacion.
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.0 ✔ readr 2.1.4
## ✔ forcats 1.0.0 ✔ stringr 1.5.0
## ✔ ggplot2 3.4.1 ✔ tibble 3.1.8
## ✔ lubridate 1.9.2 ✔ tidyr 1.3.0
## ✔ purrr 1.0.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
library(gghighlight)
library(leaflet)
library(IRdisplay)
options(scipen = 999)
options(warn = -1)
library(lubridate)
library(viridis)
## Loading required package: viridisLite
library(data.table)
##
## Attaching package: 'data.table'
##
## The following objects are masked from 'package:lubridate':
##
## hour, isoweek, mday, minute, month, quarter, second, wday, week,
## yday, year
##
## The following objects are masked from 'package:dplyr':
##
## between, first, last
##
## The following object is masked from 'package:purrr':
##
## transpose
library(caTools)
library(kernlab)
##
## Attaching package: 'kernlab'
##
## The following object is masked from 'package:purrr':
##
## cross
##
## The following object is masked from 'package:ggplot2':
##
## alpha
library(caret)
## Loading required package: lattice
##
## Attaching package: 'caret'
##
## The following object is masked from 'package:purrr':
##
## lift
library(ROSE)
## Loaded ROSE 0.0-4
## Reading in files
list.files("../input")
## character(0)
earthquake <- read_csv("../all_month.csv")
## Rows: 8161 Columns: 22
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (8): magType, net, id, place, type, status, locationSource, magSource
## dbl (12): latitude, longitude, depth, mag, nst, gap, dmin, rms, horizontalE...
## dttm (2): time, updated
##
## ℹ 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.
cols(
.default = col_double(),
time = col_datetime(format = ""),
magType = col_character(),
net = col_character(),
id = col_character(),
updated = col_datetime(format = ""),
place = col_character(),
type = col_character(),
status = col_character(),
locationSource = col_character(),
magSource = col_character()
)
## cols(
## .default = col_double(),
## time = col_datetime(format = ""),
## magType = col_character(),
## net = col_character(),
## id = col_character(),
## updated = col_datetime(format = ""),
## place = col_character(),
## type = col_character(),
## status = col_character(),
## locationSource = col_character(),
## magSource = col_character()
## )
glimpse(earthquake)
## Rows: 8,161
## Columns: 22
## $ time <dttm> 2019-03-11 04:30:18, 2019-03-11 04:24:26, 2019-03-11 …
## $ latitude <dbl> 33.52100, 61.06940, 38.77333, 65.01810, 37.29130, 35.1…
## $ longitude <dbl> -116.7945, -151.8329, -122.7435, -148.7292, -117.5088,…
## $ depth <dbl> 2.82, 105.60, 1.16, 8.60, 6.90, 5.00, 6.20, 48.70, 2.5…
## $ mag <dbl> 0.44, 1.10, 0.73, 1.60, 0.70, 1.80, 1.70, 1.90, 0.56, …
## $ magType <chr> "ml", "ml", "md", "ml", "ml", "mb_lg", "ml", "ml", "md…
## $ nst <dbl> 18, NA, 5, NA, 8, NA, 30, NA, 10, NA, NA, NA, NA, NA, …
## $ gap <dbl> 53.00, NA, 213.00, NA, 176.36, 64.00, 93.14, NA, 77.00…
## $ dmin <dbl> 0.009898, NA, 0.011220, NA, 0.375000, 0.219000, 0.1370…
## $ rms <dbl> 0.1400, 0.2500, 0.0100, 0.5100, 0.2800, 0.5100, 0.3300…
## $ net <chr> "ci", "ak", "nc", "ak", "nn", "us", "nn", "ak", "nc", …
## $ id <chr> "ci38263479", "ak01937u587x", "nc73150441", "ak01937u2…
## $ updated <dttm> 2019-03-11 04:33:55, 2019-03-11 04:27:53, 2019-03-11 …
## $ place <chr> "11km NE of Aguanga, CA", "51km NW of Nikiski, Alaska"…
## $ type <chr> "earthquake", "earthquake", "earthquake", "earthquake"…
## $ horizontalError <dbl> 0.25, NA, 1.55, NA, NA, 1.10, NA, NA, 0.42, 5.80, NA, …
## $ depthError <dbl> 1.02, 1.50, 0.70, 0.20, 24.50, 1.70, 0.70, 1.50, 1.31,…
## $ magError <dbl> 0.129, NA, 0.230, NA, NA, 0.255, NA, NA, NA, 0.080, NA…
## $ magNst <dbl> 11, NA, 2, NA, NA, 4, NA, NA, 1, 15, NA, NA, 11, 60, 1…
## $ status <chr> "automatic", "automatic", "automatic", "automatic", "a…
## $ locationSource <chr> "ci", "ak", "nc", "ak", "nn", "us", "nn", "ak", "nc", …
## $ magSource <chr> "ci", "ak", "nc", "ak", "nn", "us", "nn", "ak", "nc", …
head(earthquake)
## # A tibble: 6 × 22
## time latitude longi…¹ depth mag magType nst gap dmin
## <dttm> <dbl> <dbl> <dbl> <dbl> <chr> <dbl> <dbl> <dbl>
## 1 2019-03-11 04:30:18 33.5 -117. 2.82 0.44 ml 18 53 0.00990
## 2 2019-03-11 04:24:26 61.1 -152. 106. 1.1 ml NA NA NA
## 3 2019-03-11 04:22:42 38.8 -123. 1.16 0.73 md 5 213 0.0112
## 4 2019-03-11 04:13:42 65.0 -149. 8.6 1.6 ml NA NA NA
## 5 2019-03-11 04:10:13 37.3 -118. 6.9 0.7 ml 8 176. 0.375
## 6 2019-03-11 04:04:12 35.1 -97.6 5 1.8 mb_lg NA 64 0.219
## # … with 13 more variables: rms <dbl>, net <chr>, id <chr>, updated <dttm>,
## # place <chr>, type <chr>, horizontalError <dbl>, depthError <dbl>,
## # magError <dbl>, magNst <dbl>, status <chr>, locationSource <chr>,
## # magSource <chr>, and abbreviated variable name ¹longitude
nrow(earthquake)
## [1] 8161
Depth- La profundidad en kilometros del evento. Es relativa al nivel del mar (WGS84 geoid) o a la elevacion que presentan las estaciones que toman medidas del terremoto.
depthError- La incertidumbre en la profundidad reportada para el evento.
dmin- La distancia horizontal desde el epicentro hasta la estacion sismologica mas cercana, dada en grados. Un grado es alrededor de 111.2 Km. Entre mas pequeño sea el numero, mas confiable a a ser el calculo de la profundidad.
gap- El espacio mas grande entre estaciones Azimutalmente adyacentes, dado en grados. Entre mas pequeño sea el numero, mas confiable a a ser el calculo de la profundidad. si el espacio sobrepasa los 180 grados, existe mas incertumbre acerca de profundidad y localizacion.
horizontalError- Incertidumbre de la locolizacion reportada, dada en Km
id- Identificador unico del evento.
latitude- Latitud en grados decimales. Valores negativos para latitudes al sur.
locationSource- La fuente que originalmente reporto la localizacion del evento
longitude- Longitud en grados decimales. Valores negativos para longitudes oeste
mag- Magnitud del evento, se mide en base a la fuerza del sismo en su origen
magError- Incertidumbre de la magnitud reportada
magNst- El numero total de estaciones usadas para obtener la magnitud del evento
magSource- La fuente que originalmente reporto la magnitud del evento
magType- El metodo usado para calcular la magnitud del evento
net- La informacion del contribuidor de la informacion del evento
nst- El numero total de estaciones sismicas usadas para determinar la ubicacion del terremoto
place- Descripcion textual de la region geografica mas cercana al sitio donde ocurrio el evento, como una ciudad o un pueblo, en caso que no haya nada cercano a 300 Km, se usa la regionalizacion Flinn-Engdahl (F-E)
rms-El residuo de la media cuadratica del tiempo de viaje, en segundos.
status- Indica si el evento fue revisado por un humano, puede ser automatico o revisado
time- La hora a la que ocurrio el evento, se reporta en milisegundos desde la epoca.
type- Tipo de evento sismico
updated- La hora en que el evento fue actualizado. Se reporta en milisegundos desde la epoca.
En kos datos tomados, se presentaro alrededor de 7 sismos con una valoracion mayor a 6 en la escal de Ritcher
options(repr.plot.width=12, repr.plot.height=6)
ggplot(earthquake, aes(time, mag)) +
geom_line(color = 'steelblue')+ theme_bw()+
ggtitle("Earthquake Magnitude")+
xlab('Date')+
ylab('Magnitude')+
theme(plot.title = element_text(hjust = 0.5))
Ahora, se extrajeron 2 caracteristicas de los datos:
Localizacion del Sismo (Estado/Pais)
Momento del dia en Horas
De las lineas del siguiente grafico, podemos apreciar el numero maximo de terremotos que ocurrieron a una hora particular.
Se aprecia que medianoche es la hora a la cual el mayor numero de sismos ocurren. Alrededor de las 5 P.M. en cambio, es cuando menos se presentan. Cuando se observa la magnitud maxima por hora, 8-9 A.M. presenta el sismo de mayor impacto, con un 7.
#Location
earthquake$location <- sub('.*,\\s*','', earthquake$place)
#Time of the day in 'Hour'
earthquake$hour <- ymd_hms(earthquake$time)
earthquake$hour <- hour(earthquake$hour)
#Visualizing the number of quakes that have happened at a particular time
earthquake %>%
filter(!is.na(mag))%>%
group_by(hour)%>%
summarise(count = length(id),max_magnitude = max(mag))%>%
ggplot(aes(hour,count, color = max_magnitude))+geom_line()+
scale_color_viridis(direction = -1)+
scale_x_continuous(breaks=seq(0,23,1))+
xlab("Time of the day")+
ylab("Number of earthquakes")+
ggtitle("Number of quakes as per time of the day")+
theme_bw()+
theme(plot.title = element_text(hjust = 0.5))
En el mapa que se presenta a continuacion, se aprecian aquellos sitios
donde se presentaron los sismos mas recientes. Ademas, se presentan los
sismos de mayor magnitud mas importantes que se han dado(Entre el 18 y
el 19 de febrero y Marzo)
Place: 115km ESE of Palora, Ecuador Magnitude: 7.5 Time: 2019-02-22 10:17:22
Place: 27km NNE of Azangaro, Peru Magnitude: 7 Time: 2019-03-01 08:50:41
Place: 116km SE of L’Esperance Rock, New Zealand Magnitude: 6.4 Time: 2019-03-06 15:46:14
Place: 49km NW of Namatanai, Papua New Guinea Magnitude: 6.4 Time: 2019-02-17 14:35:55
Place: 28km S of Cliza, Bolivia Magnitude: 6.3 Time: 2019-03-15 05:03:50
Place: 260km SE of Lambasa, Fiji Magnitude: 6.2 Time: 2019-03-10 08:12:25
Place: 140km SSW of Kulumadau, Papua New Guinea Magnitude: 6.1 Time: 2019-03-10 12:48:00
bins=seq(1, 8.0, by=1.0)
palette = colorBin( palette="YlOrBr", domain=earthquake$mag, na.color="transparent", bins=bins)
d=leaflet(earthquake) %>%
addTiles() %>%
setView( lng = 166.45, lat = 21, zoom = 1.25) %>%
addProviderTiles(providers$Esri.WorldImagery) %>%
addCircleMarkers(~longitude, ~latitude,
fillColor = ~palette(mag), fillOpacity = 0.7, color="white", radius=3, stroke=FALSE,
popup = paste("Place:", earthquake$place, "<br>",
"Magnitude:", earthquake$mag, "<br>",
"Time:", earthquake$time, "<br>")) %>%
addLegend( pal=palette, values=~mag, opacity=0.9, title = "Magnitude", position = "bottomright" )
htmlwidgets::saveWidget(d, "d.html")
display_html('<iframe src="d.html" width=100% height=450></iframe>')
En el Top 30 de las localizaciones donde se han presentado la mayor cantidad se encuentran varios Estados de US asi como paises; aunque alrededor del 35% de los terremotos se presentaron en la costa oeste de los estados unidos y un 27% en Alaska, no superan una magnitud de 1.7, mientras que zonas del hemisferio sur como Chile, presentan menos sismos, pero tienen una magnitud promedio de 4.4
earthquake %>%
group_by(location) %>%
filter(!(is.na(mag)))%>%
summarise(Number_of_quakes = length(location),
Average_Magnitude = mean(mag))%>%
mutate(Percent = round(prop.table(Number_of_quakes)*100,2))%>%
arrange(desc(Number_of_quakes))%>% top_n(25, Number_of_quakes)
## # A tibble: 25 × 4
## location Number_of_quakes Average_Magnitude Percent
## <chr> <int> <dbl> <dbl>
## 1 CA 2643 1.02 32.4
## 2 Alaska 2551 1.72 31.3
## 3 Nevada 480 0.776 5.88
## 4 Utah 480 1.39 5.88
## 5 Puerto Rico 269 2.37 3.3
## 6 Hawaii 241 1.83 2.95
## 7 Montana 174 1.27 2.13
## 8 Washington 114 1.06 1.4
## 9 Indonesia 102 4.60 1.25
## 10 California 86 0.980 1.05
## # … with 15 more rows
Conocemos que la profundidad es la distancia a la que el terremoto comienza a romper, Asi que a continuacion el autor experimento si a mayor profundidad se podia producir una mayor magnitud. Se creo un grafico de dispersion de profundidad vs magnitud y se encontro que los sismos de menor magnitud suelen ocurrir a mayores profundidades (200 Km o mas), mientras que los de magniudes mayores a 6 suelen estar mas esparcidos.
ggplot(earthquake, aes(mag,depth,color = hour))+
geom_jitter(alpha = 0.5)+
gghighlight(max(depth>200)| max(mag>4))+
scale_x_continuous(breaks=seq(0,9,1))+
scale_color_viridis(direction = -1)+
theme_bw()+
xlab('Magnitude')+
ylab('Depth')+
ggtitle('Magnitude Vs. Depth in Km')+
theme(plot.title = element_text(hjust = 0.5))
Las actividades sismicas tambien pueden presentarse por actividades humanas, como explosiones en canteras, ettc; aun asi, el 98% siguen produciendose por movimientos naturales en la tierra
earthquake %>%
group_by(type)%>%
summarise(count = length(type))%>%
mutate(Percent = prop.table(count*100))%>%
ggplot(aes(type,Percent, fill = type))+
geom_col()+theme_bw()+
xlab('Type of Seismic Activity')+
ylab('Percent')+
ggtitle('Percent of Seismic Activity')+
theme(plot.title = element_text(hjust = 0.5))
Cuando visualizamos las actividades sismicas de acuerdo con su tipo,
podemos ver que gran parte de los movimientos de baja magnitud se
presentan en los Estados Unidos.
pal <- colorFactor(palette = "Accent",domain = earthquake$type)
e=leaflet(earthquake) %>%
addTiles() %>%
setView( lng = -119.417931, lat = 50.778259, zoom = 3) %>%
addProviderTiles(providers$CartoDB.Positron) %>%
addCircleMarkers(~longitude, ~latitude,
fillColor = ~pal(type), fillOpacity = 0.5, color="white", radius=3, stroke=FALSE,
popup = paste("Place:", earthquake$place, "<br>",
"Magnitude:", earthquake$mag, "<br>",
"Time:", earthquake$time, "<br>",
"Type:", earthquake$type, "<br>")) %>%
addLegend( pal=pal, values=~type, opacity=0.9, title = "Type", position = "bottomright" )
htmlwidgets::saveWidget(e, "e.html")
display_html('<iframe src="e.html" width=100% height=450></iframe>')
Sabemos que la profundidad es donde el terremoto empieza a moverse. Del grafico de caja que se encuentra abajo, podemos observar que aquellos sismos que no ocurren de forma natural se producen mayormente en la superficie, a diferencia de los naturales, que se producen varios kilometros dentro del planeta.
ggplot(earthquake, aes('',depth, color = type))+geom_boxplot()+
scale_y_continuous(limits = c(0, 100))+theme_bw()+
xlab('Type of Seismic Activity')+
ggtitle('Depth of Seismic Activity')
El siguiente parametro importante es la magnitud. De forma natural, los sismos pueden alcanzar magnitudes entre 0 y 7, mientras los causados por la actividad humana van de 0 a 2.2 en la escala Ritcher.
ggplot(earthquake, aes('',mag, color = type))+geom_boxplot()+
scale_y_continuous(limits = c(0, 8))+theme_bw()+
xlab('Type of Seismic Activity')+
ggtitle('Magnitude of Seismic Activity')
Segun se observa, en horas nocturnas como medianoche hasta las 5 A.M. se producen mayormente sismos de actividad humana.
ggplot(earthquake, aes('',hour, color = type))+geom_boxplot()+
scale_y_continuous(limits = c(0, 24))+theme_bw()+
xlab('Type of Seismic Activity')+
ggtitle('Time of Seismic Activity')
A continuacion, se va a tratar de predecir el tipo de evento sismico por medio de caracteristicas habladas anteriormente.
Primero que nada, se prepara el conjunto de datos para realizar las predicciones. Para los eventos sismicos causados por el hombre, se van a poner todos en una sola categoria ya que tienen un rango de profundidad similar.
#Choosing the relevant columns
quake <- earthquake[,c(2,3,4,5,24,15)]
#Categorising the type
quake$type <- ifelse(quake$type == 'earthquake', 'Earthquake', 'Otherquake')
#quake[,c(1:5)] <- scale(quake[,c(1:5)])
#Converting our target column 'type' into a factor
quake$type <- factor(quake$type)
#Checking and removing any row having NA
colSums(is.na(quake))
## latitude longitude depth mag hour type
## 0 0 0 4 0 0
quake <- quake[!is.na(quake$mag),]
Se usara la maquina de soporte de vectores para hacer predicciones, y se espera un problema de desequilibrio, dado que un 98% de las observaciones son eventos naturales y un 2% artiiciales.
Primero, se entreno al modelo sin tomar en cuenta el desequilibrio, y luego se aplico ROSE library para resolver el problema de equilibrio.
head(quake)
## # A tibble: 6 × 6
## latitude longitude depth mag hour type
## <dbl> <dbl> <dbl> <dbl> <int> <fct>
## 1 33.5 -117. 2.82 0.44 4 Earthquake
## 2 61.1 -152. 106. 1.1 4 Earthquake
## 3 38.8 -123. 1.16 0.73 4 Earthquake
## 4 65.0 -149. 8.6 1.6 4 Earthquake
## 5 37.3 -118. 6.9 0.7 4 Earthquake
## 6 35.1 -97.6 5 1.8 4 Earthquake
table(quake$type)
##
## Earthquake Otherquake
## 8005 152
set.seed(1234)
indices = sample.split(quake$type, SplitRatio = 0.7)
train = quake[indices,]
test = quake[!(indices),]
head(train)
## # A tibble: 6 × 6
## latitude longitude depth mag hour type
## <dbl> <dbl> <dbl> <dbl> <int> <fct>
## 1 33.5 -117. 2.82 0.44 4 Earthquake
## 2 61.1 -152. 106. 1.1 4 Earthquake
## 3 38.8 -123. 1.16 0.73 4 Earthquake
## 4 65.0 -149. 8.6 1.6 4 Earthquake
## 5 35.1 -97.6 5 1.8 4 Earthquake
## 6 37.3 -117. 6.2 1.7 3 Earthquake
table(train$type)
##
## Earthquake Otherquake
## 5604 106
table(test$type)
##
## Earthquake Otherquake
## 2401 46
set.seed(1234)
#Using RBF Kernel
Model_RBF <- ksvm(type~ ., data = train, scale = FALSE, kernel = "rbfdot")
Eval_RBF <- predict(Model_RBF, test[,-6])
#confusion matrix - RBF Kernel
confusionMatrix(Eval_RBF,test$type)
## Confusion Matrix and Statistics
##
## Reference
## Prediction Earthquake Otherquake
## Earthquake 2401 46
## Otherquake 0 0
##
## Accuracy : 0.9812
## 95% CI : (0.975, 0.9862)
## No Information Rate : 0.9812
## P-Value [Acc > NIR] : 0.5391
##
## Kappa : 0
##
## Mcnemar's Test P-Value : 0.00000000003247
##
## Sensitivity : 1.0000
## Specificity : 0.0000
## Pos Pred Value : 0.9812
## Neg Pred Value : NaN
## Prevalence : 0.9812
## Detection Rate : 0.9812
## Detection Prevalence : 1.0000
## Balanced Accuracy : 0.5000
##
## 'Positive' Class : Earthquake
##
En la prediccion de arriba, se observa con claridad el problema. Todos los terremotos naturales fueron predecidos adecuadamente, mientras que los artificiales no pudieron ser predecidos en lo mas minimo.
Solucionando el desbalanceo
Se va a aplicar el paquete de ROSE (Randomly Over Sampling Examples) para solucionar el problema con el balanceo mediate sobremuestreo y submuestreo.
set.seed(1234)
over <- ovun.sample(type~., data = train, method="over", N= 11640)$data
set.seed(1234)
#Using RBF Kernel
Model_RBF <- ksvm(type~ ., data = over, scale = FALSE, kernel = "rbfdot")
Eval_RBF <- predict(Model_RBF, test[,-6])
#confusion matrix - RBF Kernel
confusionMatrix(Eval_RBF,test$type)
## Confusion Matrix and Statistics
##
## Reference
## Prediction Earthquake Otherquake
## Earthquake 2285 4
## Otherquake 116 42
##
## Accuracy : 0.951
## 95% CI : (0.9416, 0.9592)
## No Information Rate : 0.9812
## P-Value [Acc > NIR] : 1
##
## Kappa : 0.3941
##
## Mcnemar's Test P-Value : <0.0000000000000002
##
## Sensitivity : 0.9517
## Specificity : 0.9130
## Pos Pred Value : 0.9983
## Neg Pred Value : 0.2658
## Prevalence : 0.9812
## Detection Rate : 0.9338
## Detection Prevalence : 0.9354
## Balanced Accuracy : 0.9324
##
## 'Positive' Class : Earthquake
##
Ahora se puede obsevar un aumento en la especifidad, de alrededor del 85%.