I’m looking for help in disaggregating some spatial data into smaller grid cells.
structure(list(GEOID = c("17031010100", "17031010200"), NAME.x = c("Census Tract 101, Cook County, Illinois",
"Census Tract 102, Cook County, Illinois"), median_inc = c(30708,
35932), pop = c(4835, 8830), share25_edu = c(17.1124828532236,
21.5430163706026), pop_poverty = c(1719, 2139), share_poverty = c(35.5532574974147,
24.2242355605889), median_age = c(30.3, 32.6), geometry = structure(list(
structure(list(list(structure(c(-87.677765, -87.678074, -87.675257,
-87.673257, -87.672251, -87.671657, -87.668657, -87.668657,
-87.666357, -87.6650920979757, -87.6662895604484, -87.6665966344484,
-87.67245, -87.677357, -87.677765, 42.02303, 42.023011, 42.020531,
42.019231, 42.019294, 42.019331, 42.019431, 42.019231, 42.019231,
42.0193213501446, 42.0223445264575, 42.0231197815191, 42.023031,
42.02303, 42.02303), dim = c(15L, 2L)))), class = c("XY",
"MULTIPOLYGON", "sfg")), structure(list(list(structure(c(-87.676457,
-87.679457, -87.680757, -87.683157, -87.684958, -87.684557,
-87.683957, -87.683357, -87.680457, -87.678457, -87.674857,
-87.672657, -87.670557, -87.670657, -87.670657, -87.670757,
-87.671557, -87.671657, -87.672251, -87.673257, -87.676457,
42.019131, 42.019531, 42.019531, 42.019431, 42.019431, 42.016431,
42.014131, 42.012331, 42.012531, 42.012631, 42.012731, 42.012731,
42.012731, 42.013931, 42.016031, 42.018331, 42.018031, 42.019331,
42.019294, 42.019231, 42.019131), dim = c(21L, 2L)))), class = c("XY",
"MULTIPOLYGON", "sfg"))), class = c("sfc_MULTIPOLYGON", "sfc"
), precision = 0, bbox = structure(c(xmin = -87.684958, ymin = 42.012331,
xmax = -87.6650920979757, ymax = 42.0231197815191), class = "bbox"), crs = structure(list(
input = "EPSG:4326", wkt = "GEOGCRS["WGS 84",n ENSEMBLE["World Geodetic System 1984 ensemble",n MEMBER["World Geodetic System 1984 (Transit)"],n MEMBER["World Geodetic System 1984 (G730)"],n MEMBER["World Geodetic System 1984 (G873)"],n MEMBER["World Geodetic System 1984 (G1150)"],n MEMBER["World Geodetic System 1984 (G1674)"],n MEMBER["World Geodetic System 1984 (G1762)"],n MEMBER["World Geodetic System 1984 (G2139)"],n ELLIPSOID["WGS 84",6378137,298.257223563,n LENGTHUNIT["metre",1]],n ENSEMBLEACCURACY[2.0]],n PRIMEM["Greenwich",0,n ANGLEUNIT["degree",0.0174532925199433]],n CS[ellipsoidal,2],n AXIS["geodetic latitude (Lat)",north,n ORDER[1],n ANGLEUNIT["degree",0.0174532925199433]],n AXIS["geodetic longitude (Lon)",east,n ORDER[2],n ANGLEUNIT["degree",0.0174532925199433]],n USAGE[n SCOPE["Horizontal component of 3D system."],n AREA["World."],n BBOX[-90,-180,90,180]],n ID["EPSG",4326]]"), class = "crs"), n_empty = 0L)), row.names = c(NA,
-2L), tigris = "tract", sf_column = "geometry", agr = structure(c(GEOID = NA_integer_,
NAME.x = NA_integer_, median_inc = NA_integer_, pop = NA_integer_,
share25_edu = NA_integer_, pop_poverty = NA_integer_, share_poverty = NA_integer_,
median_age = NA_integer_), class = "factor", levels = c("constant",
"aggregate", "identity")), class = c("sf", "tbl_df", "tbl", "data.frame"
))
variable_tracts has data on certain variables for all census tracts in Cook County, IL. I’m interested in those located within Chicago, which i find by
chi_tracts <- variables_tract |>
st_filter(chi_map)
where
chi_map_comm <- read_sf("https://raw.githubusercontent.com/thisisdaryn/data/master/geo/chicago/Comm_Areas.geojson")
chi_map <- st_union(chi_map_comm)
This leaves roughly 800 census tracts.
**What i want to do **
I want to disaggregate all the census tracts in chi_tracts to smaller grid cells. I want to get the geometries of every grid cell.
I’m concerned about how long this process might take – 800 census tracts is a lot.
I’m pretty lost here as to how I can approach this, so any help would be appreciated! I apologize if the formatting isn’t correct – i’m not very experienced on this forum.
I tried the following code which is shamelessly taken from chatgpt, this code runs for a long time to no avail:
split_into_grid <- function(tract, cellsize) {
grid <- st_make_grid(tract, cellsize = 0.01, what = "polygons", square = TRUE) |>
st_as_sf()
grid <- st_intersection(grid, tract)
grid <- grid |>
mutate(
median_inc = tract$median_inc,
share25_edu = tract$share25_edu,
pop = tract$pop / nrow(grid),
share_poverty = tract$share_poverty,
median_age = tract$median_age
)
return(grid)
}
cell_size <- 0.01
chi_grid <- chi_tracts |>
group_split() |>
map_dfr(~split_into_grid(.x, cell_size))
Lorens Elvang Thomassen is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
You can use just st_intersection()
between your tract {sf} object and grid.
gr <- sf::st_make_grid(variables_tract, cellsize = c(0.01, 0.01)) |>
sf::st_as_sf()
gr$id <- seq(nrow(gr))
tmap::qtm(variables_tract) +
tmap::qtm(gr, fill = "id", fill_alpha = 0.4)
When you intersects them, all variables from both sf data frames will be copied to resulting objects:
p <- variables_tract |>
sf::st_intersection(gr)
p
#> Simple feature collection with 6 features and 9 fields
#> Geometry type: POLYGON
#> Dimension: XY
#> Bounding box: xmin: -87.68496 ymin: 42.01233 xmax: -87.66509 ymax: 42.02312
#> Geodetic CRS: WGS 84
#> # A tibble: 6 × 10
#> GEOID NAME.x median_inc pop share25_edu pop_poverty share_poverty median_age
#> * <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 1703… Censu… 30708 4835 17.1 1719 35.6 30.3
#> 2 1703… Censu… 35932 8830 21.5 2139 24.2 32.6
#> 3 1703… Censu… 30708 4835 17.1 1719 35.6 30.3
#> 4 1703… Censu… 35932 8830 21.5 2139 24.2 32.6
#> 5 1703… Censu… 30708 4835 17.1 1719 35.6 30.3
#> 6 1703… Censu… 30708 4835 17.1 1719 35.6 30.3
#> # ℹ 2 more variables: id <int>, geometry <POLYGON [°]>
tmap::qtm(p, fill = "id")
Now you can group by id
(from grid) or GEOID
from variables_tract and perform your analysys.
Created on 2024-12-13 with reprex v2.1.1.9000
1