无法按空间范围筛选GTFS数据(gtfstools)

编程语言 2026-07-10

我在尝试通过合并省内多家运营商的GTFS数据,构建米兰地区的统一GTFS。

在合并之前,我需要对每个GTFS进行空间筛选,只保留在米兰区域运营的服务,因为不少运营商也在省外提供服务。

然而,在对市政运营商(ATM)的GTFS应用空间筛选时,我遇到了问题。具体来说,在筛选阶段出现了sfheaders的错误。

这个问题仅出现在ATM数据集中: i) 其他所有GTFS数据源在筛选时都没有错误地完成过滤; ii) 其中还包括甚至不包含shapes.txt文件的数据源

我已经检查过ATM GTFS中的shapes数据:i) 结构看起来有效;ii) 我在筛选前明确按shape_id和 shape_pt_sequence对其进行了排序。

尽管做了这些检查,错误仍然存在,我也无法确定根本原因。

ATM文件

STIBM shapefile

stibm_comuni = st_read(path)

stibm = stibm_comuni %>% 
  summarise(geometry = st_union(geometry))

# UPLOAD individual GTFS =======================================================
gtfs_dir = 'GTFS - Milano' # Set working directory

# Dictionary: name -> zip filename
gtfs_files <- list(
  atm       = "gtfs.zip",
  trenord   = "trenord_gtfs.zip",
  movibus   = "2026-03-06_Movibus.zip",
  stav      = "2026-01-30_STAV.zip",
  airpullman = "2025-09-25_Airpullman.zip",
  star      = "2025-07-29_STAR.zip"
)

gtfs_list <- lapply(gtfs_files, function(filename) {
  path <- file.path(gtfs_dir, filename)
  message("Reading: ", filename)
  read_gtfs(path)
})

#list2env(gtfs_list, envir = .GlobalEnv)

# Order shapes files in the list
gtfs_list <- lapply(gtfs_list, function(gtfs) {
  if (!is.null(gtfs$shapes) && nrow(gtfs$shapes) > 0) {
    shapes_dt <- as.data.table(gtfs$shapes)
    setorder(shapes_dt, shape_id, shape_pt_sequence)
    gtfs$shapes <- shapes_dt
  }

  return(gtfs)
})

# Filter each feed by STIBM boundaries
gtfs_stibm <- lapply(names(gtfs_list), function(name) {
  message("Filtering: ", name)
  tryCatch({
    result <- filter_by_spatial_extent(gtfs_list[[name]], stibm)
    message("OK: ", name)
    result
  }, error = function(e) {
    message("FAILED: ", name, " -> keeping original. Error: ", e$message)
    gtfs_list[[name]]
  })
})

where I get an error for ATM GTFS:

Filtering: atm FAILED: atm -> keeping original. Error: sfheaders - error indexing lines, perhaps caused by un-ordered data? Filtering: trenord s2/s2polyline.cc:633 WARNING S2Polyline::Shape with one vertex has no edges OK: trenord Filtering: movibus OK: movibus Filtering: stav OK: stav Filtering: airpullman OK: airpullman Filtering: star OK: star

Anyone can help on this?

解决方案

你需要在对 filter_by_spatial_extent(gtfs_list[["atm"]], stibm) 进行操作之前,先按 trip_idstop_sequencegtfs_list[["atm"]]$stop_times 进行排序。修复方法是

# Order shapes & stop_times
gtfs_list <- lapply(gtfs_list, \(gtfs) {
  if (!is.null(gtfs$shapes) && nrow(gtfs$shapes) > 0 && !is.null(gtfs$stop_times) && nrow(gtfs$stop_times) > 0) {
    data.table::setorder(gtfs$shapes, shape_id, shape_pt_sequence)
    # Stop times need to be ordered by trip_id & stop_sequence
    data.table::setorder(gtfs$stop_times, trip_id, stop_sequence)
  }
  return(gtfs)
})

Root cause

错误来自 这一行gtfstools::filter_by_spatial_extent()

trips_sf <- get_trip_geometry(gtfs_list[["atm"]], file = "stop_times")

这会因为 sort_sequence = FALSE 而抛出该错误。

如果未排序,会触发 此问题(testthat的 sfheaders:::rcpp_sf_linestring此相关的GitHub问题:

sfheaders:::rcpp_sf_linestring( data.frame(id1 = c(1,2,3), id2 = c(1,2,1), x = 1:3, y = 1:3, z = 1:3, m = 1:3), c(2L:3L), 1L, "", keep = TRUE )

最小可复现错误

因此,产生此问题所需的最小代码量,是像下面一样,在列 trip_idstop_sequence 中打乱连贯性,就像下方所示:

trip_id       = c(1,2,3)
stop_sequence = c(1,2,1)
library(gtfstools)
library(data.table)
set.seed(42)
data_path <- system.file("extdata/spo_gtfs.zip", package = "gtfstools")
gtfs <- read_gtfs(data_path)
# messing up contiguity intentionally
gtfs$stop_times <- gtfs$stop_times[sample(.N)]
filter_by_spatial_extent(gtfs, bbox) 
# or
get_trip_geometry(gtfs, file = "stop_times")

错误:sfheaders - error indexing lines, perhaps caused by un-ordered data?

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章