<- readRDS("G:/My Drive/GES486/final_proj/results/flow_lines.RDS") %>%
flow_lines st_transform(crs = 3857)
= counties(state = "MD", cb = TRUE) %>%
baltimore_bound filter(str_detect(GEOID, "24510|24005")) %>%
st_transform(crs = 3857)
Flow Mapping
Setup
This script uses outputs from the previous 3 Rmd files to create a flow map based on the mapdeck
package, and bins start and end points by hexes. This workflow is not currently automated for other datasets, but this is a minimal working example to show that it can be expanded to other metro areas.
<- st_make_grid(baltimore_bound, #create 2000m hex grid
balt_hex cellsize = c(1600,1600),
what = "polygons",
square = FALSE,
crs = 3857
%>%
) st_as_sf() %>%
mutate(hex_id = paste("hex_", row_number(), sep = ""))
<- st_intersects(st_union(baltimore_bound), balt_hex)
balt_hex.intersects <- balt_hex[balt_hex.intersects[[1]],]
balt_hex.subset <- st_centroid(balt_hex.subset) %>% st_transform(4326) #dataframe of centroids of each hex
balt_centroid <- baltimore_bound %>% st_transform(4326)
baltimore_bound tm_shape(baltimore_bound)+
tm_polygons(col = "#bdbdbd", border.col = "black", lwd = 2)+
tm_shape(balt_hex)+
tm_borders()
This next block of code is a mess, but I couldn’t get dplyr
and sf
to cooperate with some of these dataframes, which contained multiple geometry columns. This can be cleaned up (and probably will be), but for now, this works for the data that I have.
<- balt_hex %>% st_transform(4326)
balt_hex <- balt_hex.subset %>% st_transform(4326)
balt_hex.subset <- st_as_sf(flow_lines)
flow_lines_sf <- st_transform(flow_lines_sf, crs = 4326)
flow_lines_sf <- st_set_geometry(flow_lines_sf, flow_lines_sf$start_geom) %>% st_transform(4326)
flow_lines_sf <- st_join(flow_lines_sf, balt_hex.subset) #spatial join of start points (set start points as active geometry in previous step)
start_points_join <- st_set_geometry(flow_lines_sf, flow_lines_sf$end_geom) %>% st_transform(4326)
flow_lines_sf <- st_join(flow_lines_sf, balt_hex.subset) #in similar fashion, spatial join of end points
end_points_join $start_hex_id <- start_points_join$hex_id
flow_lines_sf$end_hex_id <- end_points_join$hex_id
flow_lines_sf<- left_join(st_drop_geometry(flow_lines_sf), balt_centroid, by = c("start_hex_id" = "hex_id")) #join centroid of endpoint hex to row
flow_lines_sf <- rename(flow_lines_sf, start_centroid = x)
flow_lines_sf <- left_join(flow_lines_sf, balt_centroid, by = c("end_hex_id" = "hex_id")) #likewise for end
flow_lines_sf <- rename(flow_lines_sf, end_centroid = x)
flow_lines_sf <- st_sf(flow_lines_sf) %>% st_transform(4326)
flow_lines_sf <- rename(count(flow_lines_sf, start_hex_id, end_hex_id), wgt = n)
flow_lines_arc <- flow_lines_arc %>% mutate(scale_weight = (3*wgt))
flow_lines_arc <- left_join(st_drop_geometry(flow_lines_arc), balt_centroid, by = c("end_hex_id" = "hex_id"))
flow_lines_arc <- left_join(flow_lines_arc, balt_centroid, by = c("start_hex_id" = "hex_id"))
flow_lines_arc <- flow_lines_arc %>% rename(end_centroid = x.x, start_centroid = x.y) %>% st_sf()
flow_lines_arc <- flow_lines_arc %>% st_transform(4326) flow_lines_arc
The following methodology, to count start and end points within hexes, is adapted from Matt Herman’s blog post detailing the counting of trees within NYC census geographies.
<- count(as_tibble(start_points_join), hex_id) %>% rename(start_in_hex = n)
start_hex_count <- count(as_tibble(end_points_join), hex_id) %>% rename(end_in_hex = n)
end_hex_count <- left_join(balt_hex.subset, start_hex_count, by = c("hex_id" = "hex_id"))
balt_hex.subset <- left_join(balt_hex.subset, end_hex_count, by = c("hex_id" = "hex_id"))
balt_hex.subset <- balt_hex.subset %>% replace(is.na(.), 0)
balt_hex.subset <- balt_hex.subset %>% mutate(total_endpoint = start_in_hex + end_in_hex)
balt_hex.subset <- balt_hex.subset %>% st_transform(4326) balt_hex.subset
Three flow maps can be generated from this data: one symbolized with start points per hex, one with end points per hex, and one with total endpoints per hex.
%>%
flow_lines_arc mapdeck(token = Sys.getenv("MAPBOX_TOKEN")) %>%
add_arc(origin = "start_centroid",
destination = "end_centroid",
stroke_from = "#000000",
stroke_to = "#000000",
stroke_width = "scale_weight",
update_view = TRUE) %>%
add_sf(data = balt_hex.subset,
fill_colour = "start_in_hex",
fill_opacity = 180,
legend = TRUE
)
%>%
flow_lines_arc mapdeck(token = Sys.getenv("MAPBOX_TOKEN")) %>%
add_arc(origin = "start_centroid",
destination = "end_centroid",
stroke_from = "#000000",
stroke_to = "#000000",
stroke_width = "scale_weight",
update_view = TRUE) %>%
add_sf(data = balt_hex.subset,
fill_colour = "end_in_hex",
fill_opacity = 180,
legend = TRUE
)
%>%
flow_lines_arc mapdeck(token = Sys.getenv("MAPBOX_TOKEN")) %>%
add_arc(origin = "start_centroid",
destination = "end_centroid",
stroke_from = "#000000",
stroke_to = "#000000",
stroke_width = "scale_weight",
update_view = TRUE) %>%
add_sf(data = balt_hex.subset,
fill_colour = "total_endpoint",
fill_opacity = 180,
legend = TRUE
)
if(!file.exists("../results/flow_lines_arc.RDS")){
saveRDS(flow_lines_arc, file = "../results/flow_lines_arc.RDS")
}if(!file.exists("../results/balt_hex.RDS")){
saveRDS(balt_hex, file = "../results/balt_hex.RDS")
}