Unendo poligoni in R


29

Mi chiedo come unire i poligoni spaziali usando il codice R?

Sto lavorando con i dati del censimento in cui alcune aree cambiano nel tempo e desidero unirmi ai poligoni e ai dati corrispondenti e riferire semplicemente sulle aree unite. Sto mantenendo un elenco di poligoni che hanno modificato il censimento in censimento e che ho intenzione di unire. Vorrei utilizzare questo elenco di nomi di area come elenco di ricerca da applicare ai dati del censimento di diversi anni.

Mi chiedo quale funzione R utilizzare per unire i poligoni selezionati e i rispettivi dati. L'ho cercato su Google, ma semplicemente sono diventato confuso dai risultati.


La risposta alla maggior parte delle operazioni di geometria come la dissoluzione dei poligoni, la sovrapposizione, il punto in poligono, l'intersezione, l'unione ecc. Ecc. È il pacchetto rgeos.
Spacedman

1
L'Ufficio censimento degli Stati Uniti pubblica tabelle per fare questo per gli anni 1990-2000 e 2000-2010. Essi possono essere gestiti con base di dati si unisce, che sono attuate da R's mergela funzione.
whuber

Risposte:


39

La seguente soluzione si basa su un post di Roger Bivand su R-sig-Geo . Ho preso il suo esempio sostituendo lo shapefile tedesco con alcuni dati di censimento dell'Oregon che puoi scaricare da qui (prendi tutti i componenti dello shapefile da "Contee dell'Oregon e dati di censimento").

Cominciamo con il caricamento dei pacchetti richiesti e l'importazione dello shapefile in R.

# Required packages
libs <- c("rgdal", "maptools", "gridExtra")
lapply(libs, require, character.only = TRUE)

# Import Oregon census data
oregon <- readOGR(dsn = "path/to/data", layer = "orcounty")
oregon.coords <- coordinates(oregon)

Successivamente, sono necessarie alcune variabili di raggruppamento per aggregare i dati. Nel nostro esempio, il raggruppamento si basa semplicemente sulle coordinate della singola contea. Vedi l'immagine sotto, i bordi neri indicano i poligoni originali, mentre i bordi rossi rappresentano i poligoni aggregati per oregon.id.

# Generate IDs for grouping
oregon.id <- cut(oregon.coords[,1], quantile(oregon.coords[,1]), include.lowest=TRUE)

# Merge polygons by ID
oregon.union <- unionSpatialPolygons(oregon, oregon.id)

# Plotting
plot(oregon)
plot(oregon.union, add = TRUE, border = "red", lwd = 2)

Shapefile originale e raggruppato dell'Oregon

Fin qui tutto bene. Tuttavia, gli attributi dei dati relativi alle sottoregioni dello shapefile originale (ad es. Densità di popolazione, area, ecc.) Si perdono durante l'esecuzione unionSpatialPolygons. Suppongo che desideri aggregare anche i dati del censimento associati allo shapefile, quindi avrai bisogno di un passaggio intermedio.

Devi prima convertire i tuoi poligoni in un frame di dati per eseguire l'aggregazione. Ora prendiamo le colonne degli attributi di dati da sei a otto ("AREA", "POP1990", "POP1997") e aggregiamole secondo la funzione di applicazione degli ID sopra sum.

# Convert SpatialPolygons to data frame
oregon.df <- as(oregon, "data.frame")

# Aggregate and sum desired data attributes by ID list
oregon.df.agg <- aggregate(oregon.df[, 6:8], list(oregon.id), sum)
row.names(oregon.df.agg) <- as.character(oregon.df.agg$Group.1)

Infine, riconvertisci il tuo frame di dati in un SpatialPolygonsDataFramefile di forma precedentemente unificato oregon.unione ottieni sia poligoni generalizzati che i tuoi dati di censimento derivati ​​dal precedente passaggio di aggregazione di riepilogo.

# Reconvert data frame to SpatialPolygons
oregon.shp.agg <- SpatialPolygonsDataFrame(oregon.union, oregon.df.agg)

# Plotting
grid.arrange(spplot(oregon, "AREA", main = "Oregon: original county area"), 
             spplot(oregon.shp.agg, "AREA", main = "Oregon: aggregated county area"), ncol = 1)

Aree dell'Oregon


10

Ecco una soluzione usando il pacchetto sf:

library(tidycensus)
library(dplyr)
library(sf)
library(ggplot2)

# get data from tindycensus for demonstration (note you need an API key, folow instructions here: https://walkerke.github.io/tidycensus/articles/basic-usage.html)
census <- tidycensus::get_acs(geography = "tract", variables = "B19013_001",
                           state = "TX", county = "Tarrant", geometry = TRUE) %>% 
  arrange(NAME)

# reduce dataset size
census <- census[1:8,]

# create grouping variable
group_1 <- census$GEOID[1:2]
group_2 <- census$GEOID[6:8]

census <- census %>% mutate(group = case_when(GEOID %in% group_1 ~ 'newgroup1',
                                              GEOID %in% group_2 ~ 'newgroup2',
                                              TRUE ~ GEOID))

# summarise by grouping variable (performs a union on grouped polygons and sums 'estimate')
census2 <- group_by(census, group) %>% 
  summarise(estimate = sum(estimate), do_union = TRUE)

# visualise using ggplot2 development version and facet by merged/unmerged datasets
plot_data <- rbind(census %>% select(group, estimate) %>%
                     mutate(facet = "unmerged"), 
                   census2 %>% mutate(facet = "merged"))

gp <- ggplot() + 
      geom_sf(data = plot_data, aes(fill = estimate), color = 'white') + 
      scale_fill_viridis_c() + 
      facet_wrap(~facet, ncol = 1)

inserisci qui la descrizione dell'immagine


Ho pensato di aggiungere un piccolo avvertimento qui, per ogni evenienza: attenzione all'utilizzo di summarise()derivati ​​con l' do_unionargomento, dato che ho appena fatto qualcosa del genere summarise_if(shapefile, predic.function, sum, na.rm = TRUE, do_union = TRUE), che ha finito per sommare anche un VERO in ogni cella (ovvero +1 per tutte le operazioni). Hai bisogno di indagare di più per capire se è qualcosa che dovrebbe essere segnalato (almeno per un avviso in più) ...?
Stragu
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.