351 lines
12 KiB
R
351 lines
12 KiB
R
|
|
library(ggplot2)
|
|
library(tidyr)
|
|
library(dplyr)
|
|
library(forcats)
|
|
library(ggthemes)
|
|
library(plotly)
|
|
library(htmlwidgets)
|
|
library(lubridate)
|
|
library(ggrepel)
|
|
library(zoo)
|
|
|
|
#### Total/State/Class ####
|
|
# Read in total/state/class data
|
|
d_raw <- read.csv("data/us ham radio licenses over time.csv")
|
|
|
|
# What dates do we have?
|
|
unique(d_raw$Date)
|
|
|
|
# Clean up here if needed
|
|
d <- d_raw %>%
|
|
mutate(Date = as.Date(Date)) #%>%
|
|
# Drop Tech alone and leave Tech and Tech Plus
|
|
#select(-c(Tech, Tech.Plus))
|
|
|
|
d_total <- d %>% filter(State.Territory == "TOTAL")
|
|
|
|
d_total_long <- d_total %>%
|
|
pivot_longer(cols = !c("Date", "State.Territory", "source_name", "source_detail"),
|
|
names_to = "lclass",
|
|
values_to = "count") %>%
|
|
# only keep rows with data so plots look right
|
|
filter(!is.na(count))
|
|
|
|
d_state_total_long <- d %>% filter(State.Territory != "TOTAL") %>%
|
|
select(Date, State.Territory, Total, source_name, source_detail) %>%
|
|
filter(!is.na(Total))
|
|
|
|
#### City ####
|
|
city_raw <- read.csv("data/us cities ham radio licenses over time.csv")
|
|
city <- city_raw %>% mutate(Date = as.Date(Date),
|
|
city_label = paste0(City, ", ", State))
|
|
|
|
#### License Actions ####
|
|
ae7q_actions <- read.csv("data/ae7q-actions-scraped.csv") %>%
|
|
mutate(date = as.Date(date)) %>%
|
|
filter(!is.na(action)) %>%
|
|
arrange(date) %>%
|
|
group_by(action) %>%
|
|
mutate(mean_30 = rollmean(count, k=30, fill=NA, align='right'))
|
|
|
|
# Make sure all the dates are there
|
|
#date_vec <- seq(min(ae7q_actions$date), max(ae7q_actions$date), by="days")
|
|
#all(date_vec == unique(ae7q_actions$date))
|
|
|
|
#### Plots ####
|
|
|
|
##### Total over time, y = 0 #####
|
|
ggplot(data = d_total,
|
|
aes(x = Date,
|
|
y = Total,
|
|
color = source_name)) +
|
|
geom_line() +
|
|
geom_point(size = 0.3) +
|
|
scale_x_date(date_breaks = "10 years",
|
|
date_minor_breaks = "1 year",
|
|
date_labels = "%Y") +
|
|
scale_y_continuous(labels = scales::comma,
|
|
limits = c(0, NA)) +
|
|
theme_bw() +
|
|
labs(title = "US Amateur Licenses",
|
|
caption = "w1cdn.net",
|
|
color = "Source") +
|
|
theme(legend.position="bottom")
|
|
ggplotly()
|
|
|
|
ggsave("plots/total-over-time-y.png", width = 6, height = 4)
|
|
|
|
#p <- ggplotly()
|
|
#htmlwidgets::saveWidget(as_widget(p), selfcontained = TRUE, file = "plots/total-over-time-y.html")
|
|
|
|
##### Total over time, since 2000 #####
|
|
ggplot(data = d_total %>% filter(Date >= as.Date("2000-01-01")),
|
|
aes(x = Date,
|
|
y = Total,
|
|
color = source_name)) +
|
|
geom_line() +
|
|
geom_point(size = 0.3) +
|
|
scale_x_date(date_breaks = "2 years",
|
|
date_minor_breaks = "3 months",
|
|
date_labels = "%Y") +
|
|
scale_y_continuous(labels = scales::comma) +
|
|
theme_bw() +
|
|
labs(title = "US Amateur Licenses since 2000",
|
|
caption = "w1cdn.net",
|
|
color = "Source") +
|
|
theme(legend.position="bottom")
|
|
|
|
ggsave("plots/total-over-time-2000.png", width = 6, height = 4)
|
|
|
|
##### Total over time, 2 years #####
|
|
ggplot(data = d_total %>% filter(Date >= Sys.Date() - years(2)),
|
|
aes(x = Date,
|
|
y = Total,
|
|
color = source_name)) +
|
|
geom_line() +
|
|
geom_point(size = 0.3) +
|
|
scale_x_date(date_breaks = "3 months",
|
|
date_minor_breaks = "1 month",
|
|
date_labels = "%Y-%m") +
|
|
scale_y_continuous(labels = scales::comma) +
|
|
theme_bw() +
|
|
labs(title = paste0("US Amateur Licenses since ", Sys.Date() - years(2)),
|
|
caption = "w1cdn.net",
|
|
color = "Source") +
|
|
theme(legend.position="bottom")
|
|
|
|
ggsave("plots/total-over-time-2-years.png", width = 6, height = 4)
|
|
|
|
##### ARRL Total over time, 2 months #####
|
|
ggplot(data = d_total %>% filter(Date >= Sys.Date() - months(2),
|
|
source_name == "ARRL FCC License Counts"),
|
|
aes(x = Date,
|
|
y = Total,
|
|
color = source_name)) +
|
|
geom_line() +
|
|
geom_point(size = 0.3) +
|
|
scale_x_date(date_breaks = "7 days",
|
|
date_minor_breaks = "1 days",
|
|
date_labels = "%m-%d") +
|
|
scale_y_continuous(labels = scales::comma) +
|
|
theme_bw() +
|
|
labs(title = paste0("US Amateur Licenses since ", Sys.Date() - months(2)),
|
|
caption = "w1cdn.net",
|
|
color = "Source") +
|
|
theme(legend.position="bottom")
|
|
|
|
ggsave("plots/total-over-time-2-months.png", width = 6, height = 4)
|
|
|
|
##### By license class #####
|
|
ggplot(data = d_total_long %>% filter(lclass != "Total"),
|
|
aes(x = Date,
|
|
y = count,
|
|
color = fct_reorder2(lclass, Date, count),
|
|
linetype = source_name)) +
|
|
geom_line() +
|
|
geom_point(size = 0.3) +
|
|
scale_x_date(date_breaks = "10 years",
|
|
date_minor_breaks = "1 year",
|
|
date_labels = "%Y") +
|
|
scale_y_continuous(labels = scales::comma) +
|
|
scale_color_colorblind() +
|
|
theme_bw() +
|
|
labs(title = "US Amateur Licenses by Class",
|
|
y = "Count",
|
|
color = "Class",
|
|
caption = "w1cdn.net") +
|
|
theme(legend.position="bottom")
|
|
|
|
ggsave("plots/class-over-time.png", width = 12, height = 8)
|
|
|
|
##### By license class, 2 years #####
|
|
ggplot(data = d_total_long %>% filter(lclass != "Total",
|
|
Date >= Sys.Date() - years(2)),
|
|
aes(x = Date,
|
|
y = count,
|
|
color = fct_reorder2(lclass, Date, count),
|
|
linetype = source_name)) +
|
|
geom_line() +
|
|
geom_point(size = 0.3) +
|
|
scale_x_date(date_breaks = "3 months",
|
|
date_minor_breaks = "1 month",
|
|
date_labels = "%Y-%m") +
|
|
scale_y_continuous(labels = scales::comma) +
|
|
scale_color_colorblind() +
|
|
theme_bw() +
|
|
labs(title = paste0("US Amateur Licenses by Class since ", Sys.Date() - years(2)),
|
|
y = "Count",
|
|
color = "Class",
|
|
caption = "w1cdn.net") +
|
|
theme(legend.position="bottom")
|
|
|
|
ggsave("plots/class-over-time-2-years.png", width = 6, height = 4)
|
|
|
|
##### By license class, facet #####
|
|
ggplot(data = d_total_long %>% filter(lclass != "Total"),
|
|
aes(x = Date,
|
|
y = count,
|
|
color = source_name)) +
|
|
geom_line() +
|
|
geom_point(size = 0.3) +
|
|
facet_wrap(~lclass) +
|
|
scale_x_date(date_breaks = "10 years",
|
|
date_minor_breaks = "1 year",
|
|
date_labels = "%Y") +
|
|
scale_y_continuous(labels = scales::comma) +
|
|
scale_color_colorblind() +
|
|
theme_bw() +
|
|
labs(title = "US Amateur Licenses by Class",
|
|
y = "Count",
|
|
color = "Class",
|
|
caption = "w1cdn.net") +
|
|
theme(legend.position="bottom")
|
|
|
|
ggsave("plots/class-over-time-facet.png", width = 15, height = 9)
|
|
|
|
##### By license class, stacked #####
|
|
# ggplot(data = d_total_long %>% filter(lclass != "Total"),
|
|
# aes(x = Date,
|
|
# y = count,
|
|
# fill = fct_reorder2(lclass, Date, count))) +
|
|
# geom_area() +
|
|
# scale_fill_colorblind() +
|
|
# scale_x_date(date_breaks = "10 years",
|
|
# date_minor_breaks = "1 year",
|
|
# date_labels = "%Y") +
|
|
# scale_y_continuous(labels = scales::comma) +
|
|
# theme_bw() +
|
|
# labs(title = "US Amateur Licenses by Class",
|
|
# fill = "Class",
|
|
# caption = "w1cdn.net") +
|
|
# theme(legend.position="bottom")
|
|
|
|
#ggsave("plots/class-over-time-stacked.png", width = 6, height = 4)
|
|
|
|
##### By state #####
|
|
ggplot(data = d_state_total_long,
|
|
aes(x = Date,
|
|
y = Total,
|
|
color = source_name)) +
|
|
geom_line() +
|
|
geom_point(size = 0.3) +
|
|
facet_wrap(~State.Territory,
|
|
scales = "free_y") +
|
|
scale_x_date(date_breaks = "10 years",
|
|
#date_minor_breaks = "1 year",
|
|
date_labels = "%Y") +
|
|
scale_y_continuous(labels = scales::comma) +
|
|
theme_bw() +
|
|
labs(title = "US Amateur Licenses by State",
|
|
y = "Count",
|
|
caption = "w1cdn.net") +
|
|
theme(legend.position="bottom")
|
|
|
|
ggsave("plots/states-over-time-freey.png", width = 15, height = 9)
|
|
|
|
##### By city #####
|
|
a <- city %>% group_by(city_label) %>%
|
|
mutate(plot_label = if_else(Date == max(Date),
|
|
city_label,
|
|
NA_character_)) %>%
|
|
distinct()
|
|
ggplot(data = a,
|
|
aes(x = Date,
|
|
y = Count,
|
|
color = city_label)) +
|
|
geom_line() +
|
|
geom_point(size = 0.3) +
|
|
scale_x_date(date_breaks = "1 years",
|
|
date_minor_breaks = "1 month",
|
|
date_labels = "%Y",
|
|
limits = c(NA_Date_, Sys.Date() + years(4))) +
|
|
scale_y_continuous(labels = scales::comma) +
|
|
theme_bw() +
|
|
geom_label_repel(aes(label = plot_label),
|
|
nudge_x = 1,
|
|
na.rm = TRUE,
|
|
segment.colour = NA) +
|
|
labs(title = "US Amateur Licenses by City",
|
|
y = "Count",
|
|
caption = "w1cdn.net") +
|
|
theme(legend.position="bottom") +
|
|
guides(color = "none")
|
|
|
|
ggsave("plots/cities-over-time.png", width = 15, height = 9)
|
|
|
|
##### By city, free y #####
|
|
ggplot(data = city,
|
|
aes(x = Date,
|
|
y = Count,
|
|
group = city_label,
|
|
color = source_name)) +
|
|
geom_line() +
|
|
geom_point(size = 0.3) +
|
|
facet_wrap(~city_label,
|
|
scales = "free_y"
|
|
) +
|
|
scale_x_date(date_breaks = "4 years",
|
|
date_minor_breaks = "1 years",
|
|
date_labels = "%Y") +
|
|
scale_y_continuous(labels = scales::comma) +
|
|
theme_bw() +
|
|
labs(title = "US Amateur Licenses by City",
|
|
y = "Count",
|
|
caption = "w1cdn.net") +
|
|
theme(legend.position="bottom")
|
|
|
|
ggsave("plots/cities-over-time-freey.png", width = 15, height = 9)
|
|
|
|
##### Actions Over Time #####
|
|
ggplot(data = ae7q_actions,
|
|
aes(x = date,
|
|
y = count,
|
|
color = action)) +
|
|
geom_line() +
|
|
geom_line(data = ae7q_actions,
|
|
aes(x = date,
|
|
y = mean_30),
|
|
color = "black") +
|
|
scale_x_date(date_breaks = "5 years",
|
|
date_minor_breaks = "1 year",
|
|
date_labels = "%Y") +
|
|
facet_wrap(~action,
|
|
scales = "free_y") +
|
|
theme_bw() +
|
|
labs(title = "US Amateur License Actions",
|
|
subtitle = "with 30-day rolling mean",
|
|
y = "Count",
|
|
x = "Date",
|
|
caption = "w1cdn.net; source: ae7q.com",
|
|
color = "Action") +
|
|
guides(color = "none")
|
|
|
|
ggsave("plots/actions-over-time.png", width = 6, height = 4)
|
|
|
|
##### Actions Over Time, last two years #####
|
|
ggplot(data = ae7q_actions %>% filter(date >= Sys.Date() - years(2)),
|
|
aes(x = date,
|
|
y = count,
|
|
color = action)) +
|
|
geom_line() +
|
|
geom_line(data = ae7q_actions %>% filter(date >= Sys.Date() - years(2)),
|
|
aes(x = date,
|
|
y = mean_30),
|
|
color = "black") +
|
|
scale_x_date(date_breaks = "6 months",
|
|
date_minor_breaks = "1 months",
|
|
date_labels = "%Y-%m") +
|
|
facet_wrap(~action,
|
|
scales = "free_y") +
|
|
theme_bw() +
|
|
labs(title = paste0("US Amateur License Actions since ", Sys.Date() - years(2)),
|
|
subtitle = "with 30-day rolling mean",
|
|
y = "Count",
|
|
x = "Date",
|
|
caption = "w1cdn.net; source: ae7q.com",
|
|
color = "Action") +
|
|
guides(color = "none")
|
|
|
|
ggsave("plots/actions-over-time-2-years.png", width = 9, height = 6)
|