# Load package
library(tidycensus)
library(tidyverse)
library(sf)
library(dplyr)
library(tmap)
library(ggplot2)
library(readr)
library(tidyr)
library(spdep)
# Load broadband data for Mississippi 2022 and 2024
fcc22 <- read_csv("Broadband Summary by Geography Type2022.csv")
fcc24 <- read_csv("Broadband Summary by Geography Type2025.csv")
colnames(fcc22)
## [1] "area_data_type" "geography_type" "geography_id"
## [4] "geography_desc" "geography_desc_full" "total_units"
## [7] "biz_res" "technology" "speed_02_02"
## [10] "speed_10_1" "speed_25_3" "speed_100_20"
## [13] "speed_250_25" "speed_1000_100"
colnames(fcc24)
## [1] "area_data_type" "geography_type" "geography_id"
## [4] "geography_desc" "geography_desc_full" "total_units"
## [7] "biz_res" "technology" "speed_02_02"
## [10] "speed_10_1" "speed_25_3" "speed_100_20"
## [13] "speed_250_25" "speed_1000_100"
# let filters the data by county, fiber technology, and residential for Mississippi for both years, then join in one.
# Clean Mississippi 2022
fcc22_ms <- fcc22 %>%
filter(geography_type == "County") %>%
filter(substr(geography_id, 1, 2) == "28") %>%
filter(area_data_type == "Total") %>%
filter(technology == "Fiber") %>%
filter(biz_res == "R") %>%
select(geography_desc_full, avail22 = speed_100_20) %>%
distinct()
# Clean Mississippi 2024
fcc24_ms <- fcc24 %>%
filter(geography_type == "County") %>%
filter(substr(geography_id, 1, 2) == "28") %>%
filter(area_data_type == "Total") %>%
filter(technology == "Fiber") %>%
filter(biz_res == "R") %>%
select(geography_desc_full, avail24 = speed_100_20) %>%
distinct()
head(fcc24_ms)
## # A tibble: 6 × 2
## geography_desc_full avail24
## <chr> <dbl>
## 1 Adams County, MS 0.261
## 2 Alcorn County, MS 0.995
## 3 Amite County, MS 0.00512
## 4 Attala County, MS 0.224
## 5 Benton County, MS 0.353
## 6 Bolivar County, MS 0.296
head(fcc22_ms)
## # A tibble: 6 × 2
## geography_desc_full avail22
## <chr> <dbl>
## 1 Adams, MS 0.184
## 2 Alcorn, MS 0.998
## 3 Amite, MS 0
## 4 Attala, MS 0.142
## 5 Benton, MS 0.162
## 6 Bolivar, MS 0.0449
# making sure the resulted data is correct
nrow(fcc24_ms)
## [1] 82
nrow(fcc22_ms)
## [1] 82
head(fcc22_ms)
## # A tibble: 6 × 2
## geography_desc_full avail22
## <chr> <dbl>
## 1 Adams, MS 0.184
## 2 Alcorn, MS 0.998
## 3 Amite, MS 0
## 4 Attala, MS 0.142
## 5 Benton, MS 0.162
## 6 Bolivar, MS 0.0449
## Remove county from 2024
fcc24_ms <- fcc24_ms %>%
mutate(geography_desc_full = gsub(" County", "", geography_desc_full))
## join both datasets
fcc_final <- fcc22_ms %>%
left_join(fcc24_ms, by = "geography_desc_full")
fcc_final
## # A tibble: 82 × 3
## geography_desc_full avail22 avail24
## <chr> <dbl> <dbl>
## 1 Adams, MS 0.184 0.261
## 2 Alcorn, MS 0.998 0.995
## 3 Amite, MS 0 0.00512
## 4 Attala, MS 0.142 0.224
## 5 Benton, MS 0.162 0.353
## 6 Bolivar, MS 0.0449 0.296
## 7 Calhoun, MS 0.812 0.905
## 8 Carroll, MS 0.703 0.893
## 9 Chickasaw, MS 0.696 0.784
## 10 Choctaw, MS 0.563 0.976
## # ℹ 72 more rows
# Census API
census_api_key("7712f4050792f95cda2b3af671fd0eaf1f8129c4", install = TRUE, overwrite=TRUE)
## [1] "7712f4050792f95cda2b3af671fd0eaf1f8129c4"
# Download county-level data for Mississippi
counties_ms <- get_acs(
geography = "county",
state = "MS",
variables = "B01001_001",
geometry = TRUE,
year = 2022
)
## | | | 0% | | | 1% | |= | 1% | |= | 2% | |== | 2% | |== | 3% | |== | 4% | |=== | 4% | |=== | 5% | |==== | 5% | |==== | 6% | |===== | 6% | |===== | 7% | |===== | 8% | |====== | 8% | |====== | 9% | |======= | 9% | |======= | 10% | |======= | 11% | |======== | 11% | |======== | 12% | |========= | 12% | |========= | 13% | |========== | 14% | |========== | 15% | |=========== | 15% | |=========== | 16% | |============ | 16% | |============ | 17% | |============ | 18% | |============= | 18% | |============= | 19% | |============== | 19% | |============== | 20% | |============== | 21% | |=============== | 21% | |=============== | 22% | |================ | 22% | |================ | 23% | |================= | 24% | |================= | 25% | |================== | 25% | |================== | 26% | |=================== | 27% | |=================== | 28% | |==================== | 28% | |==================== | 29% | |===================== | 29% | |===================== | 30% | |===================== | 31% | |====================== | 31% | |====================== | 32% | |======================= | 32% | |======================= | 33% | |======================== | 34% | |======================== | 35% | |========================= | 35% | |========================= | 36% | |========================== | 37% | |========================== | 38% | |=========================== | 38% | |=========================== | 39% | |============================ | 39% | |============================ | 40% | |============================ | 41% | |============================= | 41% | |============================= | 42% | |============================== | 42% | |============================== | 43% | |============================== | 44% | |=============================== | 44% | |=============================== | 45% | |================================ | 45% | |================================ | 46% | |================================= | 47% | |================================= | 48% | |================================== | 48% | |================================== | 49% | |=================================== | 49% | |=================================== | 50% | |=================================== | 51% | |==================================== | 51% | |==================================== | 52% | |===================================== | 52% | |===================================== | 53% | |===================================== | 54% | |====================================== | 54% | |====================================== | 55% | |======================================= | 55% | |======================================= | 56% | |======================================== | 56% | |======================================== | 57% | |======================================== | 58% | |========================================= | 58% | |========================================= | 59% | |========================================== | 59% | |========================================== | 60% | |========================================== | 61% | |=========================================== | 61% | |=========================================== | 62% | |============================================ | 62% | |============================================ | 63% | |============================================ | 64% | |============================================= | 64% | |============================================= | 65% | |============================================== | 65% | |============================================== | 66% | |=============================================== | 66% | |=============================================== | 67% | |=============================================== | 68% | |================================================ | 68% | |================================================ | 69% | |================================================= | 69% | |================================================= | 70% | |================================================= | 71% | |================================================== | 71% | |================================================== | 72% | |=================================================== | 72% | |=================================================== | 73% | |==================================================== | 74% | |==================================================== | 75% | |===================================================== | 75% | |===================================================== | 76% | |====================================================== | 76% | |====================================================== | 77% | |====================================================== | 78% | |======================================================= | 78% | |======================================================= | 79% | |======================================================== | 79% | |======================================================== | 80% | |======================================================== | 81% | |========================================================= | 81% | |========================================================= | 82% | |========================================================== | 82% | |========================================================== | 83% | |=========================================================== | 84% | |=========================================================== | 85% | |============================================================ | 85% | |============================================================ | 86% | |============================================================= | 87% | |============================================================= | 88% | |============================================================== | 88% | |============================================================== | 89% | |=============================================================== | 89% | |=============================================================== | 90% | |=============================================================== | 91% | |================================================================ | 91% | |================================================================ | 92% | |================================================================= | 92% | |================================================================= | 93% | |================================================================== | 94% | |================================================================== | 95% | |=================================================================== | 95% | |=================================================================== | 96% | |==================================================================== | 97% | |==================================================================== | 98% | |===================================================================== | 98% | |===================================================================== | 99% | |======================================================================| 99% | |======================================================================| 100%
# Download internet access data: total households and households with broadband
internet_22 <- get_acs(
geography = "county",
state = "MS",
variables = c(
total22 = "B28002_001",
broadband22 = "B28002_004"
),
year = 2022
) %>%
# Keep only needed columns
select(GEOID, variable, estimate) %>%
# Convert from long format to wide format
pivot_wider(names_from = variable, values_from = estimate) %>%
# Calculate new coulum which is the broadband adoption rate
mutate(adopt22 = broadband22 / total22)
# Download income data for Mississippi
income_ms <- get_acs(
geography = "county",
state = "MS",
variables = "S1901_C01_012",
year = 2022
) %>%
# Keep only GEOID and income
select(GEOID, income = estimate)
# census 2024 data
internet_24 <- get_acs(
geography = "county",
state = "MS",
variables = c(
total = "B28002_001",
broadband = "B28002_004"
),
year = 2024
) %>%
select(GEOID, variable, estimate) %>%
pivot_wider(names_from = variable, values_from = estimate) %>%
mutate(adopt24 = broadband / total)
# Clean FCC data names so they match Census county names, replaces "MS" with "Mississippi" for joining
fcc_final <- fcc_final %>%
mutate(county = gsub(", MS", ", Mississippi", geography_desc_full))
fcc_final
## # A tibble: 82 × 4
## geography_desc_full avail22 avail24 county
## <chr> <dbl> <dbl> <chr>
## 1 Adams, MS 0.184 0.261 Adams, Mississippi
## 2 Alcorn, MS 0.998 0.995 Alcorn, Mississippi
## 3 Amite, MS 0 0.00512 Amite, Mississippi
## 4 Attala, MS 0.142 0.224 Attala, Mississippi
## 5 Benton, MS 0.162 0.353 Benton, Mississippi
## 6 Bolivar, MS 0.0449 0.296 Bolivar, Mississippi
## 7 Calhoun, MS 0.812 0.905 Calhoun, Mississippi
## 8 Carroll, MS 0.703 0.893 Carroll, Mississippi
## 9 Chickasaw, MS 0.696 0.784 Chickasaw, Mississippi
## 10 Choctaw, MS 0.563 0.976 Choctaw, Mississippi
## # ℹ 72 more rows
# Combine all datasets into one
data_all <- counties_ms %>%
left_join(internet_22, by = "GEOID") %>%
left_join(internet_24, by = "GEOID") %>% # NEW
left_join(income_ms, by = "GEOID")
# Clean names
data_all <- data_all %>%
mutate(NAME = gsub(" County", "", NAME),
NAME = gsub(", Mississippi", ", MS", NAME))
# Join FCC
data_all <- data_all %>%
left_join(fcc_final, by = c("NAME" = "geography_desc_full"))
# Check summary of broadband availability for 2022, and 2024 to understand the distribution of values
summary(data_all$avail22)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.00000 0.07615 0.31620 0.35856 0.58078 0.99840
summary(data_all$avail24)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.0000 0.3050 0.6160 0.5506 0.7888 0.9985
data_all
## Simple feature collection with 82 features and 15 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: -91.65501 ymin: 30.17537 xmax: -88.09789 ymax: 34.99605
## Geodetic CRS: NAD83
## First 10 features:
## GEOID NAME variable estimate moe total22 broadband22 adopt22
## 1 28087 Lowndes, MS B01001_001 58547 NA 22651 19217 0.8483952
## 2 28121 Rankin, MS B01001_001 157185 NA 58982 52653 0.8926961
## 3 28083 Leflore, MS B01001_001 27920 NA 9656 5282 0.5470174
## 4 28149 Warren, MS B01001_001 44341 NA 16823 13200 0.7846401
## 5 28153 Wayne, MS B01001_001 19760 NA 7410 5792 0.7816464
## 6 28029 Copiah, MS B01001_001 28210 NA 9841 6968 0.7080581
## 7 28089 Madison, MS B01001_001 109257 NA 42182 38456 0.9116685
## 8 28081 Lee, MS B01001_001 83343 NA 32001 25934 0.8104122
## 9 28051 Holmes, MS B01001_001 16848 NA 5798 3650 0.6295274
## 10 28073 Lamar, MS B01001_001 64425 NA 24896 22062 0.8861665
## total broadband adopt24 income avail22 avail24 county
## 1 23006 20054 0.8716856 53687 0.6843 0.7890117 Lowndes, Mississippi
## 2 60133 55408 0.9214242 76460 0.4727 0.5766189 Rankin, Mississippi
## 3 10203 7067 0.6926394 33115 0.4445 0.6127967 Leflore, Mississippi
## 4 16772 14125 0.8421774 54117 0.1353 0.2793023 Warren, Mississippi
## 5 7681 6371 0.8294493 34875 0.6911 0.7582116 Wayne, Mississippi
## 6 10060 7994 0.7946322 46889 0.2213 0.2403995 Copiah, Mississippi
## 7 43917 40691 0.9265433 79105 0.5906 0.6653713 Madison, Mississippi
## 8 32591 27819 0.8535792 64479 0.8168 0.8529897 Lee, Mississippi
## 9 6157 4198 0.6818256 28818 0.1336 0.1565157 Holmes, Mississippi
## 10 25381 22477 0.8855837 67972 0.3081 0.5481495 Lamar, Mississippi
## geometry
## 1 MULTIPOLYGON (((-88.67125 3...
## 2 MULTIPOLYGON (((-90.25346 3...
## 3 MULTIPOLYGON (((-90.45376 3...
## 4 MULTIPOLYGON (((-91.17366 3...
## 5 MULTIPOLYGON (((-88.94294 3...
## 6 MULTIPOLYGON (((-90.73628 3...
## 7 MULTIPOLYGON (((-90.4514 32...
## 8 MULTIPOLYGON (((-88.8255 34...
## 9 MULTIPOLYGON (((-90.43168 3...
## 10 MULTIPOLYGON (((-89.65421 3...
# normalization function
norm <- function(x) {
(x - min(x, na.rm = TRUE)) /
(max(x, na.rm = TRUE) - min(x, na.rm = TRUE))
}
# Apply normalization to variables
data_all <- data_all %>%
mutate(
adopt22_n = norm(adopt22),
adopt24_n = norm(adopt24), # NEW
avail22_n = norm(avail22),
avail24_n = norm(avail24)
)
data_all <- data_all %>%
mutate(
LBAI_22 = (adopt22_n + avail22_n) / 2,
LBAI_24 = (adopt24_n + avail24_n) / 2,
change = LBAI_24 - LBAI_22
)
data_all
## Simple feature collection with 82 features and 22 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: -91.65501 ymin: 30.17537 xmax: -88.09789 ymax: 34.99605
## Geodetic CRS: NAD83
## First 10 features:
## GEOID NAME variable estimate moe total22 broadband22 adopt22
## 1 28087 Lowndes, MS B01001_001 58547 NA 22651 19217 0.8483952
## 2 28121 Rankin, MS B01001_001 157185 NA 58982 52653 0.8926961
## 3 28083 Leflore, MS B01001_001 27920 NA 9656 5282 0.5470174
## 4 28149 Warren, MS B01001_001 44341 NA 16823 13200 0.7846401
## 5 28153 Wayne, MS B01001_001 19760 NA 7410 5792 0.7816464
## 6 28029 Copiah, MS B01001_001 28210 NA 9841 6968 0.7080581
## 7 28089 Madison, MS B01001_001 109257 NA 42182 38456 0.9116685
## 8 28081 Lee, MS B01001_001 83343 NA 32001 25934 0.8104122
## 9 28051 Holmes, MS B01001_001 16848 NA 5798 3650 0.6295274
## 10 28073 Lamar, MS B01001_001 64425 NA 24896 22062 0.8861665
## total broadband adopt24 income avail22 avail24 county
## 1 23006 20054 0.8716856 53687 0.6843 0.7890117 Lowndes, Mississippi
## 2 60133 55408 0.9214242 76460 0.4727 0.5766189 Rankin, Mississippi
## 3 10203 7067 0.6926394 33115 0.4445 0.6127967 Leflore, Mississippi
## 4 16772 14125 0.8421774 54117 0.1353 0.2793023 Warren, Mississippi
## 5 7681 6371 0.8294493 34875 0.6911 0.7582116 Wayne, Mississippi
## 6 10060 7994 0.7946322 46889 0.2213 0.2403995 Copiah, Mississippi
## 7 43917 40691 0.9265433 79105 0.5906 0.6653713 Madison, Mississippi
## 8 32591 27819 0.8535792 64479 0.8168 0.8529897 Lee, Mississippi
## 9 6157 4198 0.6818256 28818 0.1336 0.1565157 Holmes, Mississippi
## 10 25381 22477 0.8855837 67972 0.3081 0.5481495 Lamar, Mississippi
## geometry adopt22_n adopt24_n avail22_n avail24_n
## 1 MULTIPOLYGON (((-88.67125 3... 0.8853692 0.8754957 0.6853966 0.7901852
## 2 MULTIPOLYGON (((-90.25346 3... 0.9656281 0.9883818 0.4734575 0.5774766
## 3 MULTIPOLYGON (((-90.45376 3... 0.3393698 0.4691339 0.4452123 0.6137082
## 4 MULTIPOLYGON (((-91.17366 3... 0.7698655 0.8085241 0.1355168 0.2797178
## 5 MULTIPOLYGON (((-88.94294 3... 0.7644420 0.7796364 0.6922075 0.7593394
## 6 MULTIPOLYGON (((-90.73628 3... 0.6311237 0.7006158 0.2216546 0.2407571
## 7 MULTIPOLYGON (((-90.4514 32... 1.0000000 1.0000000 0.5915465 0.6663610
## 8 MULTIPOLYGON (((-88.8255 34... 0.8165562 0.8344014 0.8181090 0.8542585
## 9 MULTIPOLYGON (((-90.43168 3... 0.4888514 0.4445908 0.1338141 0.1567485
## 10 MULTIPOLYGON (((-89.65421 3... 0.9537985 0.9070386 0.3085938 0.5489648
## LBAI_22 LBAI_24 change
## 1 0.7853829 0.8328404 0.04745751
## 2 0.7195428 0.7829292 0.06338636
## 3 0.3922911 0.5414210 0.14912995
## 4 0.4526912 0.5441209 0.09142976
## 5 0.7283247 0.7694879 0.04116313
## 6 0.4263892 0.4706865 0.04429731
## 7 0.7957732 0.8331805 0.03740726
## 8 0.8173326 0.8443299 0.02699735
## 9 0.3113327 0.3006697 -0.01066305
## 10 0.6311961 0.7280017 0.09680554
# Set map mode to static plots
tmap_mode("plot")
# broadband access for 2024
LBAI2024 <- tm_shape(data_all) +
tm_polygons("LBAI_24", palette = "Blues",
title = "LBAI 2024")
tmap_save(LBAI2024,"Broadband Access using Broadband Accessibility Index (LBAI) for 2024.png", width = 12, height = 6)
LBAI2024
# broadband access for 2022
LBAI2022 <-tm_shape(data_all) +
tm_polygons("LBAI_22", palette = "Blues",
title = "LBAI 2022")
tmap_save(LBAI2022,"Broadband Access using Broadband Accessibility Index (LBAI) for 2022.png", width = 12, height = 6)
LBAI2022
# the change between 2022 and 2024
changeMap <- tm_shape(data_all) +
tm_polygons("change", palette = "-RdBu",
title = "Change")
tmap_save(changeMap,"Change in Broadband Access using Broadband Accessibility Index (LBAI) between 2022–2024.png", width = 12, height = 6)
changeMap
# Scatter plot to compare 2022 vs 2024, points above red line = improvement
p_scatter <- ggplot(data_all, aes(x = LBAI_22, y = LBAI_24)) +
geom_point(size = 3) +
geom_abline(slope = 1, intercept = 0, color = "red") +
labs(
title = "Broadband Access Change (2022 vs 2024)",
x = "LBAI 2022",
y = "LBAI 2024"
)
p_scatter
# Histogram to show how change is distributed
Histogram_Change <- ggplot(data_all, aes(x = change)) +
geom_histogram(bins = 20, fill = "lightblue", color = "black") +
labs(title = "Distribution of Broadband Change")
Histogram_Change
# Save the figures
ggsave("Scatter_LBAI.png", plot = p_scatter, width = 8, height = 6)
ggsave("Histogram_Change.png", plot = Histogram_Change, width = 8, height = 6)
# Create spatial neighbors based on county borders
nb <- poly2nb(data_all)
# Convert neighbors into spatial weights
lw <- nb2listw(nb, style = "W")
# test spatial clustering for 2024 broadband access
moran.test(data_all$LBAI_24, lw)
##
## Moran I test under randomisation
##
## data: data_all$LBAI_24
## weights: lw
##
## Moran I statistic standard deviate = 7.9707, p-value = 7.892e-16
## alternative hypothesis: greater
## sample estimates:
## Moran I statistic Expectation Variance
## 0.527918899 -0.012345679 0.004594356
# test spatial clustering for 2022 broadband access
moran.test(data_all$LBAI_22, lw)
##
## Moran I test under randomisation
##
## data: data_all$LBAI_22
## weights: lw
##
## Moran I statistic standard deviate = 7.1457, p-value = 4.477e-13
## alternative hypothesis: greater
## sample estimates:
## Moran I statistic Expectation Variance
## 0.472173445 -0.012345679 0.004597633
# test spatial clustering for the change
moran.test(data_all$change, lw)
##
## Moran I test under randomisation
##
## data: data_all$change
## weights: lw
##
## Moran I statistic standard deviate = 2.9467, p-value = 0.001606
## alternative hypothesis: greater
## sample estimates:
## Moran I statistic Expectation Variance
## 0.185452539 -0.012345679 0.004505763
# Local Moran’s I to detect clusters
local_22 <- localmoran(data_all$LBAI_22, lw)
local_24 <- localmoran(data_all$LBAI_24, lw)
# Store results
data_all$local_I22 <- local_22[,1]
data_all$local_I24 <- local_24[,1]
# Map Moran’s I
map22 <- tm_shape(data_all) +
tm_polygons("local_I22", palette = "-RdBu") +
tm_layout(title = "Local Moran's I (2022)")
map24 <- tm_shape(data_all) +
tm_polygons("local_I24", palette = "-RdBu") +
tm_layout(title = "Local Moran's I (2024)")
# Show comparison map side by side
tmap_arrange(map22, map24, ncol = 2)
####store values into categories
# positive means clustered, negative means outlier
data_all$lisa22_cat <- ifelse(data_all$local_I22 > 0, "Cluster", "Outlier")
data_all$lisa24_cat <- ifelse(data_all$local_I24 > 0, "Cluster", "Outlier")
# detect hotspots and coldspots
gi <- localG(data_all$LBAI_24, lw)
gi2 <- localG(data_all$LBAI_22, lw)
# store results
data_all$hotspot24 <- as.numeric(gi)
data_all$hotspot22 <- as.numeric(gi2)
# Map hotspots
HS24 <- tm_shape(data_all) +
tm_polygons("hotspot24", palette = "-RdBu") +
tm_layout(title = "Hotspot Analysis (2024)")
##
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_tm_polygons()`: migrate the argument(s) related to the scale of
## the visual variable `fill` namely 'palette' (rename to 'values') to fill.scale
## = tm_scale(<HERE>).
## [v3->v4] `tm_layout()`: use `tm_title()` instead of `tm_layout(title = )`
HS22 <- tm_shape(data_all) +
tm_polygons("hotspot22", palette = "-RdBu") +
tm_layout(title = "Hotspot Analysis (2022)")
## [v3->v4] `tm_layout()`: use `tm_title()` instead of `tm_layout(title = )`
# show comparison map side by side
tmap_arrange(HS22, HS24, ncol = 2)
## Multiple palettes called "rd_bu" found: "brewer.rd_bu", "matplotlib.rd_bu". The first one, "brewer.rd_bu", is returned.
## [scale] tm_polygons:() the data variable assigned to 'fill' contains positive and negative values, so midpoint is set to 0. Set 'midpoint = NA' in 'fill.scale = tm_scale_intervals(<HERE>)' to use all visual values (e.g. colors)
## [cols4all] color palettes: use palettes from the R package cols4all. Run
## `cols4all::c4a_gui()` to explore them. The old palette name "-RdBu" is named
## "rd_bu" (in long format "brewer.rd_bu")[plot mode] fit legend/component: Some legend items or map compoments do not
## fit well, and are therefore rescaled.
## ℹ Set the tmap option `component.autoscale = FALSE` to disable rescaling.Multiple palettes called "rd_bu" found: "brewer.rd_bu", "matplotlib.rd_bu". The first one, "brewer.rd_bu", is returned.
## [scale] tm_polygons:() the data variable assigned to 'fill' contains positive and negative values, so midpoint is set to 0. Set 'midpoint = NA' in 'fill.scale = tm_scale_intervals(<HERE>)' to use all visual values (e.g. colors)
## [cols4all] color palettes: use palettes from the R package cols4all. Run
## `cols4all::c4a_gui()` to explore them. The old palette name "-RdBu" is named
## "rd_bu" (in long format "brewer.rd_bu")[plot mode] fit legend/component: Some legend items or map compoments do not
## fit well, and are therefore rescaled.
## ℹ Set the tmap option `component.autoscale = FALSE` to disable rescaling.
map_change <- tm_shape(data_all) +
tm_polygons("change", palette = "-RdBu") + # red = increase, blue = decrease
tm_layout(title = "Change in Broadband Access Local Moran’s I (2022–2024)")
tmap_arrange(map22, map24, map_change, ncol = 3)
map_changeHS <- tm_shape(data_all) +
tm_polygons("change", palette = "-RdBu") + # red = increase, blue = decrease
tm_layout(title = "Change in Broadband Hotspots (2022–2024)")
tmap_arrange(HS22, HS24, map_changeHS, ncol = 3)
# Local Moran comparison
comp_moran <- tmap_arrange(map22, map24, ncol = 2)
tmap_save(comp_moran, "Comparison_Moran.png", width = 12, height = 6)
# Hotspot comparison
comp_hotspot <- tmap_arrange(HS22, HS24, ncol = 2)
tmap_save(comp_hotspot, "Comparison_Hotspot.png", width = 12, height = 6)
# Final comparison (2022, 2024, Change)
final_mapHS <- tmap_arrange(HS22, HS24, map_changeHS, ncol = 3)
tmap_save(final_mapHS, "HSFinal_Comparison.png", width = 14, height = 6)
# Final comparison (2022, 2024, HSChange)
final_map <- tmap_arrange(map22, map24, map_change, ncol = 3)
tmap_save(final_map, "Final_Comparison.png", width = 14, height = 6)