library(readr)
cyber_events_2026_02_13 <- read_csv("cyber_events_2026-02-13.csv")
## Rows: 16382 Columns: 46
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (24): country, change_log, county, description, industry, event_subtype,...
## dbl (22): oecd, year, csto, industry_code, opec, five_eyes, gulf_coop, shang...
## 
## ℹ 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.
cyber_events <- cyber_events_2026_02_13
##  [1] "Oklahoma"        NA                "Texas"           "Connecticut"    
##  [5] "Undetermined"    "Minnesota"       "Oregon"          "New York"       
##  [9] "Illinois"        "Washington D.C." "California"      "Delaware"       
## [13] "Florida"         "Massachusetts"   "Pennsylvania"    "Alaska"         
## [17] "Arkansas"        "Georgia"         "North Carolina"  "Missouri"       
## [21] "Virginia"        "Rhode Island"    "Alabama"         "Tennessee"      
## [25] "Puerto Rico"     "Ohio"            "Kansas"          "Maryland"       
## [29] "New Jersey"      "Kentucky"        "Michigan"        "Washington"     
## [33] "Colorado"        "Louisiana"       "New Mexico"      "Arizona"        
## [37] "Indiana"         "Nevada"          "South Carolina"  "Hawaii"         
## [41] "Wisconsin"       "Idaho"           "Maine"           "Utah"           
## [45] "New Hampshire"   "West Virginia"   "Iowa"            "Nebraska"       
## [49] "Wyoming"         "Virgin Islands"  "Mississippi"     "North Dakota"   
## [53] "Vermont"         "South Dakota"    "Montana"         "Guam"           
## [57] "undetermined"
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.3.3
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(ggplot2)
library(maps)
## Warning: package 'maps' was built under R version 4.3.3
# Clean state names
cyber_clean <- cyber_events %>%
  filter(!is.na(state),
         state != "Undetermined",
         state != "undetermined") %>%
  mutate(state = tolower(state),
         state = ifelse(state == "washington d.c.", "district of columbia", state))

# Count frequency
state_counts <- cyber_clean %>%
  count(state)
states_map <- map_data("state")

map_data_joined <- states_map %>%
  left_join(state_counts, by = c("region" = "state"))
ggplot(map_data_joined, aes(x = long, y = lat, group = group, fill = n)) +
  geom_polygon(color = "black") +
  coord_fixed(1.3) +
  scale_fill_gradient(low = "lightyellow", high = "darkred", na.value = "white") +
  theme_void() +
  labs(title = "Cyber Attack Events by State",
       fill = "Frequency")

state_summary <- cyber_clean %>%
  group_by(state) %>%
  summarise(
    n = n(),
    first_event = min(event_date, na.rm = TRUE),
    last_event  = max(event_date, na.rm = TRUE)
  )
map_data_joined <- states_map %>%
  left_join(state_summary, by = c("region" = "state"))
map_data_joined$hover_text <- paste0(
  "State: ", map_data_joined$region,
  "<br>Events: ", map_data_joined$n,
  "<br>First Event: ", map_data_joined$first_event,
  "<br>Last Event: ", map_data_joined$last_event
)
library(plotly)
## 
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:graphics':
## 
##     layout
p <- ggplot(map_data_joined, 
            aes(x = long, y = lat, group = group, fill = n, text = hover_text)) +
  geom_polygon(color = "black") +
  coord_fixed(1.3) +
  scale_fill_distiller(palette = "YlOrRd", direction = 1, na.value = "white") +
  theme_void() +
  labs(title = "Cyber Events by State From 2014 to February 13, 2026",
       fill = "Frequency")

ggplotly(p, tooltip = "text")