Unindo polígonos em R

29

Eu estou querendo saber como unir polígonos espaciais usando o código R?

Estou trabalhando com dados do censo em que determinadas áreas mudam ao longo do tempo e desejo unir os polígonos e os dados correspondentes e simplesmente informar sobre as áreas unidas. Estou mantendo uma lista de polígonos que têm alterações de censo a censo e que pretendo mesclar. Gostaria de usar esta lista de nomes de áreas como uma lista de pesquisa para aplicar aos dados do censo de diferentes anos.

Eu estou querendo saber qual função R usar para mesclar polígonos selecionados e respectivos dados. Eu pesquisei no Google, mas simplesmente fiquei confuso com os resultados.

Geoconfundido
fonte
A resposta para a maioria das operações de geometria, como dissolução de polígonos, sobreposição, ponto no polígono, interseção, união, etc, é o pacote rgeos.
Spacedman
1
O US Census Bureau publica tabelas para fazer isso para 1990-2000 e 2000-2010. Eles podem ser geridos com base de dados de junta, que são implementadas por R's mergefunção.
whuber

Respostas:

39

A solução a seguir é baseada em uma postagem de Roger Bivand no R-sig-Geo . Tomei seu exemplo substituindo o shapefile alemão por alguns dados do censo do Oregon que você pode baixar aqui (pegue todos os componentes do shapefile em 'municípios do Oregon e dados do censo').

Vamos começar carregando os pacotes necessários e importando o shapefile para o 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)

Em seguida, você precisa de alguma variável de agrupamento para agregar os dados. No nosso exemplo, o agrupamento é simplesmente baseado nas coordenadas do condado. Veja a imagem abaixo: bordas pretas indicam os polígonos originais, enquanto bordas vermelhas representam polígonos agregados por 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 original e agrupado em Oregon

Por enquanto, tudo bem. No entanto, atributos de dados relacionados às sub-regiões do shapefile original (por exemplo, densidade populacional, área etc.) são perdidos durante a execução unionSpatialPolygons. Acho que você também gostaria de agregar seus dados do censo associados ao shapefile, por isso precisará de uma etapa intermediária.

Primeiro você precisa converter seus polígonos em um quadro de dados para realizar a agregação. Agora vamos pegar as colunas de atributo de dados de seis a oito ("AREA", "POP1990", "POP1997") e agregá-las de acordo com os IDs acima, aplicando a função 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)

Por fim, reconverta seu quadro de dados novamente em um arquivo SpatialPolygonsDataFrameshapefile previamente unificado oregon.unione você obtém polígonos generalizados e seus dados de censo derivados da etapa de agregação de resumo acima.

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

Áreas de Oregon

fdetsch
fonte
10

Aqui está uma solução usando o pacote 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)

insira a descrição da imagem aqui

sebdalgarno
fonte
Eu pensei em adicionar um pequeno aviso aqui, apenas no caso: cuidado summarise()com o uso de derivativos com o do_unionargumento, como eu fiz algo parecido summarise_if(shapefile, predic.function, sum, na.rm = TRUE, do_union = TRUE), que acabou somando um VERDADEIRO em cada célula (ou seja, +1 para todas as operações). Precisa investigar mais para descobrir se isso deve ser relatado (pelo menos para um aviso extra) ...?
stragu 5/07