Преобразовать фрейм данных, содержащий координаты полигонов, в sf - PullRequest
2 голосов
/ 22 мая 2019

Я новичок в пакете sf, и у меня возникают некоторые трудности с преобразованием моего фрейма данных в sf объект.

У меня есть фрейм данных, содержащий координаты многоугольников в каждой строке. Эти координаты находятся в одном столбце.

Вот пример структуры моего фрейма данных:

dat <- tibble::tribble(
    ~code,    ~geometry,
    "MIE",    list(c(1.24, 45), c(1.25, 45), c(1.25, 46), c(1.24, 45)),
    "MIS",    list(c(1.23, 44), c(1.23, 45), c(1.24, 45), c(1.23, 44))
    )

Я хочу сделать объект sf из этого фрейма данных, но R не может распознать столбец геометрии.

Я пробовал списочные форматы и функции, такие как st_sf(), st_geometry(), st_polygon(), но безуспешно.

Попытка st_sf(dat) возвращает:

Ошибка в st_sf(dat):

Error in st_sf(dat) : no simple features geometry column present

Попытка st_polygon(dat$geometry) возвращает:

Error in vapply(x, ncol, 0L) : values must be length 1,
  but FUN(X[[1]]) result is length 0

Есть ли способ преобразовать мой фрейм данных в объект sf?

Я работаю с R версией 3.6.0.

1 Ответ

1 голос
/ 23 мая 2019

Я тоже всегда борюсь с этим преобразованием sf, потому что оно не прямое.

Первым шагом (и сложной частью) является создание st_object (здесь st_polygon) для каждой представленной индивидуальной геометрии.

Для этого преобразуйте каждый существующий list в matrix. Как только каждое представление многоугольника представляет собой n-строку matrix (по одной строке для каждой точки), мы преобразуем матрицу в один элемент list для подачи в st_polygon(). Теперь dat$geometry - это список, соответствующим образом классифицированный как POLYGONS.

library(tidyverse)

dat %>%
  mutate(geometry = map(geometry,
                        ~ do.call(rbind, .) %>% # make each list a matrix
                          list() %>% # st_polygon() requires a list
                          st_polygon()
                    )
         ) %>% 
  st_as_sf()

Затем последним шагом будет вызов st_as_sf() для всего фрейма данных. Он автоматически определит теперь правильно отформатированный столбец geometry и создаст для вас новый красивый объект sf. Счастливого отображения!

РЕДАКТИРОВАТЬ : Если вы хотите построить полигоны с отверстиями, процесс аналогичен. st_polygon() будет обрабатывать многоэлементный список, как если бы первый элемент был многоугольником, а остальные элементы - отверстиями в первом. Это требует, чтобы вы использовали map дважды, потому что вам все еще нужно построить матрицу из каждого элемента списка, но нужно сохранить списки сгруппированных матриц вместе для обработки дырок.

dat2 <- tibble::tribble( ~code, ~geometry, "MIE", list(list(c(1.24, 45), c(1.25, 45), c(1.25, 46), c(1.24, 45)), list(c(1.245,45.5), c(1.246,45.7), c(1.245,45.5))) )

 dat %>%
  mutate(geometry = map(dat$geometry,
                        ~ map(.,
                          ~ do.call(rbind, .) # make each list a matrix
                          ) %>% 
                        st_polygon()
                        )
  ) %>% 
  st_as_sf()
...