我正在处理一些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读取匹配的形状,然后查找具有匹配的纬度和经度的停靠点,但这似乎无法可靠地工作。有人知道怎么做吗?
答案 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>;
通常,您还会为JOIN
或WHERE
子句中使用的每个列创建索引,在这种情况下,这意味着:
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;在纽约曼哈顿
将为您提供一个json Feed,然后您可以在路线M1上为两个方向提取公共汽车站。