如何使用GTFS列出与路线相关的所有停靠点?

时间:2012-11-15 22:36:17

标签: google-api gtfs

我正在处理一些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读取匹配的形状,然后查找具有匹配的纬度和经度的停靠点,但这似乎无法可靠地工作。有人知道怎么做吗?

6 个答案:

答案 0 :(得分:34)

正如您所注意到的,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>;

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

CREATE INDEX stop_times_trip_id_index ON stop_times(trip_id);

CREATE INDEX trips_route_id_index ON trips(route_id);

(请注意,RDBMSes通常会自动为每个表索引其主键,因此无需在stops.stop_id上显式创建索引。)

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

答案 1 :(得分:9)

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

只是为了给你一些轶事证据,对于大约50mb的GTFS提要,Simon的查询需要10到25秒才能完成。以下陈述始终如一地&lt; 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

<强>更新

我意识到我之前没有提到这一点,但当然你会希望有每个表加入的索引。

答案 2 :(得分: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

答案 3 :(得分: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 

答案 4 :(得分:0)

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

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进行排序,则停靠站将按照行程中的顺序进行排序。

答案 5 :(得分:-1)

如果您使用&#34; onebusaway&#34;,有一种快速的方法可以在不触及GTFS的情况下执行此操作

让我们说你想知道巴士路线的巴士站&#34; M1&#34;在纽约曼哈顿

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

将为您提供一个json Feed,然后您可以在路线M1上为两个方向提取公共汽车站。