问题:根据时间,纬度和经度数据流,确定两名骑自行车的人是否一起骑行,计算效率最高的方法是什么?
背景:我是一名狂热的自行车手,想要反向设计Strava如何将自行车骑手组合在一起。以下是他们确定骑自行车者是否骑在一起的方法(他们使用时间和骑行的纬度/经度):https://support.strava.com/hc/en-us/articles/216919497-Why-don-t-I-get-grouped-in-Activities-when-I-rode-ran-with-others-
骑自行车完成后,我每秒钟都有一个纬度和经度文件。
你可以看到骑士1和2骑在一起,但是骑士2从另一个地方开始并且稍后加入了骑士1。
尽管从不同地点开始,但我想用最少计算密集的方式来确定这两个骑手一起骑行。
我认为Strava的方法很好 - 基本上在路线上的每个点周围建立一个接近区域(150米)并比较骑车者的路线,看看车手们是否将他们70%的时间都花在150米之内。
骑手1 - 地点:
2016-03-27T11:47:45Z 42.113059 -87.736485
2016-03-27T11:47:46Z 42.113081 -87.736511
2016-03-27T11:47:47Z 42.113105 -87.736538
2016-03-27T11:47:48Z 42.113142 -87.736564
2016-03-27T11:47:49Z 42.113175 -87.736587
骑手2 - 地点:
- 2016-03-27T11:47:45Z 42.113049 -87.736394< =查找骑手1的同一时间并确定是否在150米范围内。如果< 150米分配1,如果> 150分配0。
我会在Rider 1的每个点上迭代Rider 2的每个点。然后总结1和0。如果(1和0的总和)/(总点数)大于70%,则将乘客组合在一起。
我认为这种方法通常会起作用,但似乎非常耗费计算量,特别是如果有数千名骑手需要评估。此外,数据并不总是每秒都有纬度和经度。一种方法是每分钟平均一次位置,并按分钟比较平均位置。至少它会将迭代次数减少60次。
我希望有一些统计或GIS方法来建立路线的“签名”并比较签名而不是逐点比较。
有关如何以最有效的方式计算路线比较的任何想法?
注意:我在GIS论坛上发布了一个类似的问题,但还没有人回复。虽然,我认为这里写的问题更清楚。
https://gis.stackexchange.com/questions/187019/strava-activity-route-grouping
答案 0 :(得分:1)
我将假设以下情况属实:
在这种情况下,数据库中的一个表包含分析所需的所有数据。让我们看看两个骑车人C1和C2的相似之处是什么样的。
╔════╦════╦════╦════╦════╦═══════╗
║ T ║ X1 ║ Y1 ║ X2 ║ Y2 ║ D ║
╠════╬════╬════╬════╬════╬═══════╣
║ 1 ║ 10 ║ 15 ║ - ║ - ║ - ║
║ 2 ║ 11 ║ 16 ║ - ║ - ║ - ║
║ 3 ║ 11 ║ 17 ║ 19 ║ 11 ║ 10,00 ║
║ 4 ║ 12 ║ 18 ║ 18 ║ 11 ║ 9,22 ║
║ 5 ║ 12 ║ 17 ║ 17 ║ 12 ║ 7,07 ║
║ 6 ║ - ║ - ║ 15 ║ 12 ║ - ║
║ 7 ║ 13 ║ 16 ║ 14 ║ 13 ║ 3,16 ║
║ 8 ║ 13 ║ 15 ║ 13 ║ 14 ║ 1,00 ║
║ 9 ║ 14 ║ 14 ║ 13 ║ 14 ║ 1,00 ║
║ 10 ║ 14 ║ 13 ║ 14 ║ 13 ║ 0,00 ║
║ 11 ║ 14 ║ 14 ║ 14 ║ 14 ║ 0,00 ║
║ 12 ║ 14 ║ 15 ║ 14 ║ 14 ║ 1,00 ║
║ 13 ║ 15 ║ 15 ║ 15 ║ 15 ║ 0,00 ║
║ 14 ║ 15 ║ 16 ║ 15 ║ 16 ║ 0,00 ║
║ 15 ║ 16 ║ 16 ║ 16 ║ 17 ║ 1,00 ║
║ 16 ║ 17 ║ 18 ║ 16 ║ 16 ║ 2,24 ║
╚════╩════╩════╩════╩════╩═══════╝
这种比较可以使用例如在数据库中选择,为两个骑自行车者自行加入一张桌子。对于合理数量的行(例如,< 10E5,< 10E6)并且正确设置索引,该计算根本不是资源密集型的。特别是如果我们考虑到数据库查询可以以这样的方式编写,即不为每个位置输出值D,而是计算jut以便聚合(计数)该值。在这种情况下,您只需要一个行数的比率,其中D小于您的首选阈值D0与行总数相等。如果该比率等于或高于您的限制(例如,70%),骑自行车的人会一起乘车。
我们来看一个例子。如果数据库中有这样的表,名为CyclistPosition:
...包含以下数据:
╔═══════════╦═══════════════════════╦═══════════╦════════════╗
║ CyclistId ║ SamplingTime ║ Long ║ Lat ║
╠═══════════╬═══════════════════════╬═══════════╬════════════╣
║ 1 ║ 2016-03-27T11:47:45Z ║ 42,113059 ║ -87,736485 ║
║ 1 ║ 2016-03-27T11:47:46Z ║ 42,113081 ║ -87,736511 ║
║ 1 ║ 2016-03-27T11:47:47Z ║ 42,113105 ║ -87,736538 ║
║ 1 ║ 2016-03-27T11:47:48Z ║ 42,113142 ║ -87,736564 ║
║ 1 ║ 2016-03-27T11:47:49Z ║ 42,113175 ║ -87,736587 ║
║ 2 ║ 2016-03-27T11:47:45Z ║ 42,113059 ║ -87,736394 ║
║ 2 ║ 2016-03-27T11:47:46Z ║ 42,113085 ║ -87,736481 ║
║ 2 ║ 2016-03-27T11:47:47Z ║ 42,113103 ║ -87,736531 ║
║ 2 ║ 2016-03-27T11:47:48Z ║ 42,113139 ║ -87,736572 ║
║ 2 ║ 2016-03-27T11:47:49Z ║ 42,113147 ║ -87,736595 ║
╚═══════════╩═══════════════════════╩═══════════╩════════════╝
...然后我们可以使用以下方法为骑车人1和2提取数据:
SELECT SamplingTime, Long, Lat FROM CyclistPosition WHERE CyclistId = 1
SELECT SamplingTime, Long, Lat FROM CyclistPosition WHERE CyclistId = 2
...并使用此查询交叉引用该数据......
SELECT
cp1.SamplingTime,
Long1 = cp1.Long,
Lat1 = cp1.Lat,
Long2 = cp2.Long,
Lat2 = cp2.Lat
FROM
CyclistPosition cp1
JOIN CyclistPosition cp2
ON cp2.SamplingTime = cp1.SamplingTime
WHERE
cp1.CyclistId = 1
AND cp2.CyclistId = 2
我们现在有这种输出,如果我们包括rougly计算的X和Y(使用墨卡托),我们得到:
╔═══════════════════════╦═══════════╦════════════╦═══════════╦════════════╦══════════════╗
║ SamplingTime ║ Long1 ║ Lat1 ║ Long2 ║ Lat2 ║ Dm ║
╠═══════════════════════╬═══════════╬════════════╬═══════════╬════════════╬══════════════╣
║ 2016-03-27T11:47:45Z ║ 42,113059 ║ -87,736485 ║ 42,113059 ║ -87,736394 ║ 10,118517 ║
║ 2016-03-27T11:47:46Z ║ 42,113081 ║ -87,736511 ║ 42,113085 ║ -87,736481 ║ 3,334919 ║
║ 2016-03-27T11:47:47Z ║ 42,113105 ║ -87,736538 ║ 42,113103 ║ -87,736531 ║ 0,777079 ║
║ 2016-03-27T11:47:48Z ║ 42,113142 ║ -87,736564 ║ 42,113139 ║ -87,736572 ║ 0,890572 ║
║ 2016-03-27T11:47:49Z ║ 42,113175 ║ -87,736587 ║ 42,113147 ║ -87,736595 ║ 0,900635 ║
╚═══════════════════════╩═══════════╩════════════╩═══════════╩════════════╩══════════════╝
请注意,对于以米为单位的距离的粗略计算,您必须找到公式;我用过这里的那个:
http://bluemm.blogspot.hr/2007/01/excel-formula-to-calculate-distance.html
现在我们必须聚合数据并对其进行计数。我们必须将数据限制为开始和结束时间(T1
和T2
),并确定骑车人骑在一起的最大距离(D0
)。在SQL中执行此操作的简单方法是:
DECLARE @togetherPositions int
DECLARE @allPositions int
DECLARE @ratio decimal(18,2)
SELECT @togetherPositions = count(*)
FROM
CyclistPosition cp1
JOIN CyclistPosition cp2
ON cp2.SamplingTime = cp1.SamplingTime
WHERE
cp1.SamplingTime BETWEEN @T1 AND @T2
AND {formula to get distance in meters} <= @D0
SELECT @allPositions = count(*)
FROM
CyclistPosition cp1
JOIN CyclistPosition cp2
ON cp2.SamplingTime = cp1.SamplingTime
WHERE
cp1.SamplingTime BETWEEN @T1 AND @T2
SET @ratio = @togetherPositions / @allPositions * 1.0
现在你只需要决定比率是0.7,0.8,0.85 ......
HTH