st_join по геометрии и группировке столбца вместе - PullRequest
2 голосов
/ 12 июля 2020

Если у вас есть данные временных рядов пространственных точек и полигонов, как вы выполняете пространственное соединение / слияние и «нормальное» слияние непространственных переменных вместе?

Точечные данные за годы, которые я хочу объединить в годовые многоугольники, а затем суммировать (xvar) по годам:

#spatial point data by year
library(sf)
set.seed(10)
df_point <- data.frame(id = c(1, 1, 1, 1, 2, 2, 2, 2, 3, 3,
                              4, 4, 5, 5,
                              6, 6, 7, 7), 
                       year = c(2016, 2017, 2018, 2019, 2016, 2017, 2018, 2019, 2016, 2017,
                                2016, 2017, 2016, 2017,
                                2016, 2017, 2016, 2017),
                       xvar = sample(1:10, 18, replace = T))
df_point$geometry <- st_cast(st_sfc(st_multipoint(rbind(c(.1, .2), c(.1, .2), c(.1, .2), c(.1, .2),
                                                        c(.3, 1), c(.3, 1), c(.3, 1), c(.3, 1),
                                                        c(1, 1), c(1, 1),
                                                        
                                                        c(2, 2.1), c(2, 2.1), c(2.2, 2.4), c(2.2, 2.4),
                                                        c(4, 2.1), c(4, 2.1), c(4, 2.2), c(4, 2.2)))), "POINT")
                                                        
df_point <- st_as_sf(df_point)
df_point
# Simple feature collection with 18 features and 3 fields
# geometry type:  POINT
# dimension:      XY
# bbox:           xmin: 0.1 ymin: 0.2 xmax: 4 ymax: 2.4
# CRS:            NA
# First 10 features:
#    id year xvar        geometry
# 1   1 2016    9 POINT (0.1 0.2)
# 2   1 2017   10 POINT (0.1 0.2)
# 3   1 2018    7 POINT (0.1 0.2)
# 4   1 2019    8 POINT (0.1 0.2)
# 5   2 2016    6   POINT (0.3 1)
# 6   2 2017    7   POINT (0.3 1)
# 7   2 2018    3   POINT (0.3 1)
# 8   2 2019    8   POINT (0.3 1)
# 9   3 2016   10     POINT (1 1)
# 10  3 2017    7     POINT (1 1)

и данные многоугольника:

df_poly <- data.frame(poly_id = c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3), 
                      year = rep(2016:2019, each = 3))  
pol = st_polygon(list(rbind(c(0, 0), c(2, 0), c(2, 2), c(0, 2), c(0, 0))))
b = st_sfc(pol, pol + c(2, 2), pol + c(4, .8))
df_poly$geomtry <- c(b, b, b, b)
df_poly <- st_as_sf(df_poly)
df_poly
# Simple feature collection with 12 features and 2 fields
# geometry type:  POLYGON
# dimension:      XY
# bbox:           xmin: 0 ymin: 0 xmax: 6 ymax: 4
# CRS:            NA
# First 10 features:
#    poly_id year                        geomtry
# 1        1 2016 POLYGON ((0 0, 2 0, 2 2, 0 ...
# 2        2 2016 POLYGON ((2 2, 4 2, 4 4, 2 ...
# 3        3 2016 POLYGON ((4 0.8, 6 0.8, 6 2...
# 4        1 2017 POLYGON ((0 0, 2 0, 2 2, 0 ...
# 5        2 2017 POLYGON ((2 2, 4 2, 4 4, 2 ...
# 6        3 2017 POLYGON ((4 0.8, 6 0.8, 6 2...
# 7        1 2018 POLYGON ((0 0, 2 0, 2 2, 0 ...
# 8        2 2018 POLYGON ((2 2, 4 2, 4 4, 2 ...
# 9        3 2018 POLYGON ((4 0.8, 6 0.8, 6 2...
# 10       1 2019 POLYGON ((0 0, 2 0, 2 2, 0 ...

Желаемый результат:

df_sf_merge
# Simple feature collection with 12 features and 3 fields
# geometry type:  POLYGON
# dimension:      XY
# bbox:           xmin: 0 ymin: 0 xmax: 6 ymax: 4
# CRS:            NA
#    poly_id year total_sum                        geomtry
# 1        1 2016        25 POLYGON ((0 0, 2 0, 2 2, 0 ...
# 2        2 2016        32 POLYGON ((2 2, 4 2, 4 4, 2 ...
# 3        3 2016        14 POLYGON ((4 0.8, 6 0.8, 6 2...
# 4        1 2017        24 POLYGON ((0 0, 2 0, 2 2, 0 ...
# 5        2 2017        22 POLYGON ((2 2, 4 2, 4 4, 2 ...
# 6        3 2017        12 POLYGON ((4 0.8, 6 0.8, 6 2...
# 7        1 2018        10 POLYGON ((0 0, 2 0, 2 2, 0 ...
# 8        2 2018        NA POLYGON ((2 2, 4 2, 4 4, 2 ...
# 9        3 2018        NA POLYGON ((4 0.8, 6 0.8, 6 2...
# 10       1 2019        16 POLYGON ((0 0, 2 0, 2 2, 0 ...
# 11       2 2019        NA POLYGON ((2 2, 4 2, 4 4, 2 ...
# 12       3 2019        NA POLYGON ((4 0.8, 6 0.8, 6 2...

Общий подход для одного момента времени будет примерно таким:

df_sf_merge <- df_poly %>% 
  st_join(df_point) %>%  #AND MERGE OF YEAR?
  group_by(poly_id, year) %>% #year.x or year.y
  summarise(total_sum = sum(xvar, na.rm = T))

, но это не сработает, потому что слияние создает повторяющиеся копии:

df_sf_merge <- df_poly %>% 
  st_join(df_point) %>% 
  dplyr::arrange(id, year.x)
df_sf_merge
# Simple feature collection with 88 features and 5 fields
# geometry type:  POLYGON
# dimension:      XY
# bbox:           xmin: 0 ymin: 0 xmax: 6 ymax: 4
# CRS:            NA
# First 10 features:
#    poly_id year.x id year.y xvar                        geomtry
# 1        1   2016  1   2016    9 POLYGON ((0 0, 2 0, 2 2, 0 ...
# 2        1   2016  1   2017   10 POLYGON ((0 0, 2 0, 2 2, 0 ...
# 3        1   2016  1   2018    7 POLYGON ((0 0, 2 0, 2 2, 0 ...
# 4        1   2016  1   2019    8 POLYGON ((0 0, 2 0, 2 2, 0 ...
# 5        1   2017  1   2016    9 POLYGON ((0 0, 2 0, 2 2, 0 ...
# 6        1   2017  1   2017   10 POLYGON ((0 0, 2 0, 2 2, 0 ...
# 7        1   2017  1   2018    7 POLYGON ((0 0, 2 0, 2 2, 0 ...
# 8        1   2017  1   2019    8 POLYGON ((0 0, 2 0, 2 2, 0 ...
# 9        1   2018  1   2016    9 POLYGON ((0 0, 2 0, 2 2, 0 ...
# 10       1   2018  1   2017   10 POLYGON ((0 0, 2 0, 2 2, 0 ...

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

Я не уверен если вы можете выполнить пространственное и обычное соединение одновременно, но я уверен, что есть более легкая работа?

Есть предложения? спасибо

1 Ответ

1 голос
/ 13 июля 2020

Одно из решений - разделить два фрейма данных на два списка, состоящих из отдельных фреймов данных для каждого года, а затем перебрать их, используя map2(). Итак, 2016 точек получает st_joined() ed только для полигонов 2016, а 2017 указывает на полигоны 2017, et c.

map2_dfr() совпадает с map2(), за исключением того, что он сглаживает результирующий список в фрейм данных.

library(dplyr)
library(purrr)
df_point_list <- split(select(df_point, -year), # drop the year column for one of these objects so we don't get year.x and year.y
                       df_point$year)
df_poly_list <- split(df_poly, df_poly$year)


df_sf_merge<- map2_dfr(df_poly_list, df_point_list,
                         ~ .x %>% 
                           st_join(.y) %>% 
                           group_by(poly_id, year) %>% 
                           summarise(total_sum = sum(xvar, na.rm = T)))

df_sf_merge

Simple feature collection with 12 features and 3 fields
geometry type:  POLYGON
dimension:      XY
bbox:           xmin: 0 ymin: 0 xmax: 6 ymax: 4
CRS:            NA
First 10 features:
   poly_id year total_sum                        geomtry
1        1 2016        25 POLYGON ((0 0, 2 0, 2 2, 0 ...
2        2 2016        32 POLYGON ((2 2, 4 2, 4 4, 2 ...
3        3 2016        14 POLYGON ((4 0.8, 6 0.8, 6 2...
4        1 2017        24 POLYGON ((0 0, 2 0, 2 2, 0 ...
5        2 2017        22 POLYGON ((2 2, 4 2, 4 4, 2 ...
6        3 2017        12 POLYGON ((4 0.8, 6 0.8, 6 2...
7        1 2018        10 POLYGON ((0 0, 2 0, 2 2, 0 ...
8        2 2018         0 POLYGON ((2 2, 4 2, 4 4, 2 ...
9        3 2018         0 POLYGON ((4 0.8, 6 0.8, 6 2...
10       1 2019        16 POLYGON ((0 0, 2 0, 2 2, 0 ...
...