如何使用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读取匹配的形状,然后寻找纬度和经度匹配的站点,但这似乎不可靠。有人知道怎么做吗?

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

不过,请记住,这将为路线所服务的的每个站点输出一条记录。如果你正在为骑手生成时间表信息,你可能会想将查询限制为仅限今天运行的行程,以及仅限在接下来的三十分钟内出发的停靠时间。


更新:我按照自己的方式编写了上面的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);

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

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

我在谷歌搜索中发现了这篇文章,我想我会用一个更好的答案来更新它,以防其他人偶然发现它。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

更新:

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

如果从trips中选择GROUP BY shape_id,则可以使查询速度更快。

使用@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

如果你在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 

如果需要停止的方向,则应更改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排序,则停靠站将按行程中的顺序进行排序。

如果您使用"onebusaway",有一种快速的方法可以在不接触GTFS 的情况下完成此操作

假设你想知道纽约曼哈顿"M1"公交线路的公交车站

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

会给你一个json提要,然后你可以提取M1路线上两个方向的公交车站。

相关内容

  • 没有找到相关文章

最新更新