19

我正在处理一些GTFS数据,并希望能够创建与路线相关的所有站点的列表。我真的不明白如何处理 GTFS 数据。

Trips.txt 的格式如下:

route_id,service_id,trip_id,trip_headsign,direction_id,block_id,shape_id 1,A20120610WKD,A20120610WKD_000800_1..S03R,SOUTH FERRY,1,,1..S03R 1,A20120610WKD,A20120610WKD_002700_1..S03R,SOUTH FERRY,1,,1..S03R 1,A20120610WKD,A20120610WKD_004700_1..S03R,SOUTH FERRY,1,,1..S03R 1,A20120610WKD,A20120610WKD_006700_1..S03R,SOUTH FERRY,1,,1..S03R 1,A20120610WKD,A20120610WKD_008700_1..S03R,SOUTH FERRY,1,,1..S03R

我尝试使用 shape_id 读取匹配的形状,然后寻找具有匹配纬度和经度的停靠点,但这似乎并不可靠。有人知道怎么做这个吗?

4

6 回答 6

44

正如您所注意到的,GTFS 中的路线和停靠点之间没有直接关系。相反,停靠点与行程相关联,其中每次行程代表车辆沿特定路线的一次“运行”。这反映了这样一个事实,即一条路线不一定始终服务于它的每个站点——例如,在周末它可能会跳过高中以外的站点。

因此,获取路线服务的每个站点的列表需要结合几个模型:

  • routes.txt为您提供您感兴趣的路线的路线 ID。
  • trips.txt为您提供该路线的一组行程 ID。
  • stop_times.txt为您提供一组停靠点 ID,用于在每次旅行中服务的停靠点。
  • stops.txt为您提供有关每个站点的信息。

假设您使用 SQL 数据库来存储 GTFS 数据,您可能会使用这样的查询(一旦您获得了路由 ID):

SELECT stop_id, stop_name FROM stops WHERE stop_id IN (
  SELECT DISTINCT stop_id FROM stop_times WHERE trip_id IN (
    SELECT trip_id FROM trips WHERE route_id = <route_id>));

但是请记住,这将为该路线曾经服务的每个站点输出一条记录。如果您正在为骑手生成时间表信息,您可能希望将查询限制为仅在今天运行的行程,并且仅在接下来的 30 分钟内出发的停止时间。


更新:我按照我的方式编写了上面的 SQL 查询,因为我觉得它最简单地说明了 GTFS 模型之间的关系,但是 btse 是正确的(在他下面的回答中),这样的查询实际上永远不会在生产中使用。它太慢了。您将改为使用表连接和索引来保持合理的查询时间。

这是一个等效的查询,以更适合复制和粘贴到实际应用程序的方式编写:

SELECT DISTINCT stops.stop_id, stops.stop_name
  FROM trips
  INNER JOIN stop_times ON stop_times.trip_id = trips.trip_id
  INNER JOIN stops ON stops.stop_id = stop_times.stop_id
  WHERE route_id = <route_id>;

通常,您还会为JOINorWHERE子句中使用的每一列创建一个索引,在这种情况下,这意味着:

CREATE INDEX stop_times_trip_id_index ON stop_times(trip_id);

CREATE INDEX trips_route_id_index ON trips(route_id);

(请注意,RDBMS 通常通过主键自动为每个表建立索引,因此无需显式创建索引stops.stop_id。)

许多进一步的优化是可能的,这取决于所使用的特定 DBMS 以及您为性能牺牲磁盘空间的意愿。但是这些命令几乎可以在任何 RDBMS 上产生良好的性能,而不会不必要地牺牲清晰度。

于 2012-11-30T18:38:50.407 回答
10

我在谷歌搜索中看到了这篇文章,我想我会用更好的答案更新它,以防其他人偶然发现它。Simon 给出的答案是 100% 正确的,但是,对于大型 GTFS 提要,他提供的查询相当慢。这是一个执行相同操作但执行速度明显更快的查询。

只是为了给你一些轶事证据,对于大约 50mb 的 GTFS 提要,Simon 的查询需要 10-25 秒才能完成。下面的语句始终花费 < 0.2 秒。

SELECT T3.stop_id, T3.stop_name 
FROM trips AS T1
JOIN
stop_times AS T2
ON T1.trip_id=T2.trip_id AND route_id = <routeid>
JOIN stops AS T3
ON T2.stop_id=T3.stop_id
GROUP BY T3.stop_id, T3.stop_name

更新:

我意识到我之前没有提到这一点,但当然你会希望在每个表被连接的地方都有索引。

于 2013-07-05T16:53:32.497 回答
3

如果您GROUP BY shape_id在从中选择时trips可以使查询更快。

使用@btse 的查询获取两条路线的唯一停靠点需要 1.147 秒。

我的等效查询需要 0.4 秒。

SELECT unique_stops.route_id, unique_stops.stop_id, stop_name, stop_desc, stop_lat, stop_lon
FROM
  stops,
  (SELECT stop_id, route_id
   FROM
     stop_times,
     (SELECT trip_id, route_id
      FROM trips
      WHERE route_id IN (801, 803)
      GROUP BY shape_id
     ) AS unique_trips
   WHERE stop_times.trip_id = unique_trips.trip_id
   GROUP BY stop_id) AS unique_stops
WHERE stops.stop_id = unique_stops.stop_id
于 2014-02-15T20:51:58.467 回答
0

如果您在 R 中工作,您可以执行此操作来查找停靠在目标目的地 X 的路线:

require(dplyr)

routesX <- routes %>%
  left_join(trips %>% select(trip_id, route_id, shape_id)) %>%
  left_join(stop_times %>% select(trip_id, stop_id)) %>%
  semi_join(stops %>% filter(grepl('X', stop_name, ignore.case = T)), by = c('stop_id' = 'stop_code')) %>%
  select(names(routes), shape_id) %>%
  unique 
于 2018-04-23T00:34:31.447 回答
0

如果需要停止的方向,则应更改 Lukmaan 的答案:

SELECT unique_stops.route_id, unique_stops.stop_id, stop_name, stop_desc, stop_lat, stop_lon, unique_stops.direction_id
FROM
  stops,
  (SELECT stop_id, route_id, direction_id
   FROM
     stop_times,
     (SELECT trip_id, route_id, direction_id
      FROM trips
      WHERE route_id IN (801, 803)
      GROUP BY direction_id
     ) AS unique_trips
   WHERE stop_times.trip_id = unique_trips.id
   GROUP BY stop_id, direction_id) AS unique_stops
WHERE stops.stop_id = unique_stops.stop_id

如果您也stop_times.stop_sequence以相同的方式添加,并按方向和 stop_sequence 排序,则停靠点将按照行程中的顺序进行排序。

于 2020-01-22T06:43:56.033 回答
-1

如果你使用“onebusaway”,有一种快速的方法可以做到这一点,而无需接触 GTFS

假设您想知道纽约市曼哈顿巴士路线“M1”的巴士站

http://bustime.mta.info/api/where/stops-for-route/MTA%20NYCT_M1.json?key=yourapikey&includePolylines=false&version=2

将为您提供 json 提要,然后您可以提取路线 M1 上双向的巴士站。

于 2014-09-12T14:30:05.953 回答