Приєднання багатокутників в R


29

Мені цікаво, як об’єднати просторові багатокутники за допомогою коду R?

Я працюю з даними перепису, де певні ділянки змінюються з часом, і я хочу приєднатись до полігонів та відповідних даних і просто повідомити про об’єднані області. Я веду список багатокутників, які переписували зміни до перепису, і які я планую об'єднати. Я хотів би використовувати цей список назв областей як список пошуку, який застосовується до даних перепису населення різних років.

Мені цікаво, яку функцію R використовувати для об'єднання вибраних полігонів та відповідних даних. Я переглянув це, але просто заплутався в результатах.


Відповідь на більшість геометричних операцій, таких як розчинення багатокутника, накладення, точка-в-багатокутник, перетин, з'єднання тощо, - це пакет rgeos.
Спайдермен

1
Бюро перепису населення США публікує таблиці для цього в 1990-2000 та 2000-2010 роках. Ними можна керувати приєднаннями до бази даних , які реалізуються функцією R's merge.
whuber

Відповіді:


39

Наступне рішення засноване на публікації Роджера Біванда на R-sig-Geo . Я взяв його приклад заміни німецького формфайлу на деякі дані перепису з Орегону, які ви можете завантажити звідси (візьміть усі компоненти формфайлу з «Орегонських графств та даних перепису»).

Почнемо з завантаження необхідних пакетів та імпортування файлу форм у 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)

Далі вам потрібна певна змінна групування для агрегування даних. У нашому прикладі групування просто спирається на єдині координати округу. Дивіться на зображенні нижче, чорні рамки позначають оригінальні багатокутники, тоді як червоні межі представляють собою багатокутники, зведені по 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)

Оригінальний і згрупований файл форми Oregon

Все йде нормально. Однак атрибути даних, пов’язані з субрегіонами вихідного формату (наприклад, щільність населення, площа тощо), втрачаються при виконанні unionSpatialPolygons. Напевно, ви хочете також зібрати свої дані перепису, пов’язані з файлом форми, тому вам знадобиться проміжний крок.

Спочатку потрібно перетворити свої багатокутники в кадр даних, щоб здійснити агрегацію. Тепер візьмемо колонки з атрибутами даних шість-вісім ("AREA", "POP1990", "POP1997") та об'єднаємо їх відповідно до вищезазначеної функції застосування ідентифікаторів 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)

Нарешті, поверніть ваш кадр даних назад до SpatialPolygonsDataFrameнадання раніше уніфікованого файлу форм, oregon.unionі ви отримаєте як узагальнені багатокутники, так і дані перепису даних, отримані з вищевказаного кроку зведення.

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

Райони штату Орегон


10

Ось рішення за допомогою пакету 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)

введіть тут опис зображення


Я подумав, що я просто додам тут невелике попередження, про всяк випадок: будьте обережні, використовуйте summarise()похідні з do_unionаргументом, так як я просто робив щось на кшталт summarise_if(shapefile, predic.function, sum, na.rm = TRUE, do_union = TRUE), яке в кінцевому підсумку також підсумовувало TRUE у кожній комірці (тобто +1 для всіх операцій). Потрібно розглянути більше, щоб зрозуміти, чи це щось, про що слід повідомити (принаймні, для додаткового попередження) ...?
страгу
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.