За последние недели я получил противоречивые результаты при использовании векторных слоев в R с использованием пакета terra. Например, используя этот набор данных: http://www.soest.hawaii.edu/pwessel/gshhg/gshhg-shp-2.3.7.zip
Месяц назад проделал такие действия (использовал GSHHS_f_L1.shp но такая проблема случилась с несколькими слоями в zip файле):
library(terra)
xx<-vect('~/GSHHS_f_L1.shp')
plot(xx)
is.valid(xx)
TRUE
Сюжет и все остальное работает отлично
Неделю назад я сделал это снова, используя тот же слой. Сюжет сработал хорошо, но
is.valid(xx)
FALSE
yy<-makeValid(xx)
is.valid(yy)
TRUE
и снова все заработало нормально. Однако в последние дни я получил эту ошибку (тот же слой), которую до сих пор не могу решить.
is.valid(xx)
Error: IllegalArgumentException: Points of LinearRing do not form a closed linestring
yy<-makeValid(xx)
Error: IllegalArgumentException: Points of LinearRing do not form a closed linestring
После этого сюжет — единственное работающее действие. Я пробую обычное решение — создание 0-буфера, но получаю ту же ошибку. Я обновил Терру и снова скачал zip-файл, но ничего не изменилось. Я знаю некоторые альтернативы использованию sf, но с terra мне очень комфортно, и я хочу знать, есть ли решение с использованием этого пакета. Я использую R 4.4.0, terra 1.7.78 на ноутбуке Linux Ubuntu 22.04.4 LTS. Единственное изменение за последние недели заключалось в том, что я установил пакет gower с github. Любая рекомендация будет очень признательна





На моем компьютере с Win10 я обнаружил что-то странное с данными (или, возможно, это ошибка?), которое произошло при применении решения sf, но не при использовании только terra. Когда я применил terra::makeValid() ко всему набору данных, это сработало. Однако эквивалент sf::st_make_valid() не работал с полным набором данных. Я добавил потенциальное обходное решение, предназначенное только для terra, вдохновленное проблемой sf, которое, надеюсь, подойдет вам на вашей машине. Я также включил опцию sf в качестве иллюстрации, главным образом, чтобы подчеркнуть странное поведение, которое может указывать на проблему, с которой вы столкнулись.
Во-первых, используя только terra:
library(terra)
# Load data
xx <- vect('~/GSHHS_f_L1.shp')
# Check validity
unique(is.valid(xx))
# [1] TRUE FALSE
# Return valid
xx_is <- xx[is.valid(xx)]
unique(is.valid(xx_is))
# [1] TRUE
# Return invalid
xx_not <- xx[!is.valid(xx)]
is.valid(xx_not)
# [1] FALSE
# Make valid
xx_is1 <- makeValid(xx_not)
is.valid(xx_is1)
# [1] TRUE
# Recreate xx
xx <- vect(c(xx_is, xx_is1))
unique(is.valid(xx))
# [1] TRUE
Используя sf:
library(terra)
library(sf)
library(dplyr)
xx <- vect('~/GSHHS_f_L1.shp')
# xx SpatVector to sf
xx_sf <- st_as_sf(xx) %>%
st_make_valid() %>% # Does not work, but subsequent steps do not work without it either
mutate(valid = st_is_valid(.))
# Check for invalid geometries (should not return any FALSE but does for some reason)
unique(st_is_valid(xx_sf))
# [1] TRUE FALSE
# Return invalid polygon
not_valid <- filter(xx_sf, !valid)
st_is_valid(not_valid)
# [1] FALSE
# Make valid
is_valid <- st_make_valid(not_valid)
st_is_valid(is_valid)
# [1] TRUE
# Find index of oringinal invalid polygon
intersects <- st_intersects(is_valid, xx_sf)
# Sparse geometry binary predicate list of length 1, where the predicate was
# `intersects'
# 1: 2245
# Return invalid polygon
xx_sf_inv <- xx_sf[2245,]
xx_sf_inv
# Simple feature collection with 1 feature and 7 fields
# Geometry type: MULTIPOLYGON
# Dimension: XY
# Bounding box: xmin: -69.78281 ymin: 43.75223 xmax: -69.70734 ymax: 43.88222
# Geodetic CRS: WGS 84
# id level source parent_id sibling_id area geometry valid
# 2245 2380 1 WVS -1 -1 45.04373 MULTIPOLYGON (((-69.76185 4... FALSE
# Filter out invalid polygon from xx_sf
xx_sf <- filter(xx_sf, id != 2380)
# Add valid version of polygon back to xx_sf
xx_sf <- rbind(xx_sf, is_valid)
# Recheck geometries
unique(st_is_valid(xx_sf))
# [1] TRUE
# Convert back to SpatVector
xx <- vect(xx_sf)
# Recheck geometries again
unique(is.valid(xx))
# [1] TRUE
Большое спасибо. Вариант 1 в терре решить проблему.
@user3369539 user3369539 — Это была очень любопытная ошибка. Я убежден, что проблема, которую я определил с помощью sf, такая же, как и та, с которой вы столкнулись, используя terra. По какой-то неизвестной причине это проявляется по-другому, возможно, из-за разных сред R? Раньше у меня случались подобные «слабости», когда ранее работавшие сценарии начинали выдавать ошибки. Как и в вашем случае, я подозреваю, что до тех пор, пока не произошли эти ошибки, мне просто «повезло». Другими словами, что-то помешало обнаружить ошибку. В любом случае, рад, что решение нашлось.
Не вижу ни одного очевидного компонента
gower, который мог бы мешать объектамterra. Не удалось воспроизвести проблему на компьютере с Win10 с помощьюterra_1.7-78иR R 4.4.0. Запускis.valid(xx)вернул, как и ожидалось, двоичный вектор. У побережья штата Мэн, США, есть единственный полигон с неверной геометрией.