library(mapgl) # pak::pak("walkerke/mapgl") library(tidycensus) library(dplyr) library(viridisLite) # Get viridis colors viridis_colors <- viridis(5) # Get median household income by county in Texas tx_income <- get_acs( geography = "county", state = "TX", variables = "B19013_001", year = 2023, geometry = TRUE ) %>% mutate( # Format income with comma separator income_formatted = scales::dollar(estimate, accuracy = 1), # Create income categories for styling income_category = case_when( estimate < 50000 ~ "low", estimate < 75000 ~ "medium", estimate < 100000 ~ "high", TRUE ~ "very high" ), # Calculate margin of error percentage moe_percent = round((moe / estimate) * 100, 1), # Calculate percentile for progress bar (0-100) income_percentile = round(percent_rank(estimate) * 100) ) # Create the map with an awesome styled popup mapboxgl(style = mapbox_style("dark"), bounds = tx_income) %>% add_fill_layer( id = "income", source = tx_income, fill_color = interpolate( column = "estimate", values = c(25000, 50000, 75000, 100000, 125000), stops = viridis_colors, na_color = "#808080" ), popup = concat( '
', # CSS animations '', # Decorative background element with rotation animation '
', # County name with icon '

', '', '', '', get_column("NAME"), '

', # Income display with animated badge '
', '
', '
Median Household Income
', '
', get_column("income_formatted"), '
', '
', # Stats grid with conditional coloring '
', # MOE card '
', '
Margin of Error
', '
±', get_column("moe_percent"), '%
', '
', # Category card with conditional background (using viridis-inspired colors) '
', '
Income Level
', '
', get_column("income_category"), '
', '
', '
', # Animated progress bar with cleaner percentile display '
', '
', 'Percentile: ', get_column("income_percentile"), '
', '
', '
', '
', '
', '
', # Data source footer '
', '', '', '', 'American Community Survey 2023 (5-year estimates)', '
', '
' ) ) %>% add_continuous_legend( colors = viridis_colors, values = c("$25k", "$50k", "$75k", "$100k", "$125k"), legend_title = "Median Household Income", position = "bottom-left", margin_bottom = 30 )