Zusammenfügen von Polygonen in R

29

Ich frage mich, wie ich räumliche Polygone mit R-Code verbinden kann.

Ich arbeite mit Volkszählungsdaten, bei denen sich bestimmte Bereiche im Laufe der Zeit ändern, und ich möchte die Polygone und die entsprechenden Daten verbinden und einfach über die verbundenen Bereiche berichten. Ich führe eine Liste von Polygonen, die sich von Volkszählung zu Volkszählung ändern und die ich zusammenführen möchte. Ich möchte diese Liste der Gebietsnamen als Nachschlageliste für Volkszählungsdaten aus verschiedenen Jahren verwenden.

Ich frage mich, welche R-Funktion verwendet werden soll, um ausgewählte Polygone und die entsprechenden Daten zusammenzuführen. Ich habe es gegoogelt, aber einfach durch die Ergebnisse verwirrt.

Geokonfus
quelle
Die Antwort auf die meisten Geometrieoperationen wie Polygonauflösung, Überlagerung, Punkt-in-Polygon, Schnittpunkt, Vereinigung usw. usw. ist das RGEOS-Paket.
Spacedman
1
Das US Census Bureau veröffentlicht dazu Tabellen für 1990-2000 und 2000-2010. Sie können mit Datenbankverknüpfungen verwaltet werden , die von Rder mergeFunktion implementiert werden .
Whuber

Antworten:

39

Die folgende Lösung basiert auf einem Beitrag von Roger Bivand zu R-sig-Geo . Ich habe sein Beispiel genommen, in dem das deutsche Shapefile durch einige Volkszählungsdaten aus Oregon ersetzt wurde, die Sie hier herunterladen können .

Beginnen wir mit dem Laden der erforderlichen Pakete und dem Importieren des Shapefiles 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)

Als nächstes benötigen Sie eine Gruppierungsvariable, um die Daten zu aggregieren. In unserem Beispiel basiert die Gruppierung einfach auf den einzelnen Kreiskoordinaten. In der Abbildung unten geben schwarze Ränder die ursprünglichen Polygone an, während rote Ränder die durch aggregierten Polygone darstellen 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)

Originales und gruppiertes Oregon Shapefile

So weit, ist es gut. Datenattribute, die sich auf die Unterregionen des ursprünglichen Shapefiles beziehen (z. B. Bevölkerungsdichte, Fläche usw.), gehen jedoch bei der Ausführung verloren unionSpatialPolygons. Sie möchten wahrscheinlich auch Ihre mit dem Shapefile verknüpften Volkszählungsdaten aggregieren, sodass Sie einen Zwischenschritt benötigen.

Sie müssen zuerst Ihre Polygone in einen Datenrahmen konvertieren, um die Aggregation durchzuführen. Nehmen wir nun die Datenattributspalten sechs bis acht ("AREA", "POP1990", "POP1997") und aggregieren Sie sie gemäß den oben angegebenen Funktions-IDs 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)

Zum Schluss konvertieren Sie Ihren Datenrahmen wieder in ein SpatialPolygonsDataFramezuvor einheitliches Shapefile oregon.unionund Sie erhalten sowohl verallgemeinerte Polygone als auch Ihre Volkszählungsdaten, die aus dem obigen Schritt der Zusammenfassungsaggregation abgeleitet wurden.

# 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)

Oregon-Bereiche

fdetsch
quelle
10

Hier ist eine Lösung mit dem sf-Paket:

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)

Bildbeschreibung hier eingeben

sebdalgarno
quelle
Ich dachte, ich würde hier nur eine kleine Warnung hinzufügen, nur für den Fall , dass man keine summarise()Derivate mit dem do_unionArgument verwendet, da ich gerade so etwas gemacht habe summarise_if(shapefile, predic.function, sum, na.rm = TRUE, do_union = TRUE), was dazu führte, dass in jeder Zelle auch ein WAHR summiert wurde (dh +1 für alle Operationen). Müssen Sie weitere Nachforschungen anstellen, um herauszufinden, ob dies gemeldet werden sollte (zumindest für eine zusätzliche Warnung) ...?
Stragu