2017-01-06 1 views
3

Я пытаюсь выяснить расстояние между первой записью и оставшимися 3 записями группы, которая сгруппирована по Id1. Например, расстояние между (33.6008949, -83.83803) и (33.604248, -83.86729); расстояние между (33.6008949, -83.83803) и (33.60586, -83.8711) и расстояние между (33.6008949, -83.83803) и (33.6043777, -83.86624).Найти расстояние между первой и оставшейся строками в группе

Row Id1  Id2   StartTime    StopTime    Latitude Longitude DateTime   
    1  71  34   2016-11-21 00:41:05 UTC 2016-11-21 00:47:06 UTC 33.6008949 -83.83803 2016-11-21 00:43:42 UTC  
    2  71  44   2016-11-21 00:54:55 UTC 2016-11-21 00:56:28 UTC 33.604248  -83.86729 2016-11-21 00:55:18 UTC  
    3  71  45   2016-11-21 02:08:17 UTC 2016-11-21 02:09:52 UTC 33.60586  -83.8711 2016-11-21 02:09:03 UTC  
    4  71  67   2016-11-21 02:16:02 UTC 2016-11-21 02:17:21 UTC 33.6043777 -83.86624 2016-11-21 02:16:28 UTC 

Для расчета расстояния между точками, я использую ниже функции:

from math import radians, cos, sin, asin, sqrt 
    def haversine(lon1, lat1, lon2, lat2): 
     lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2]) 
     dlon = lon2 - lon1 
     dlat = lat2 - lat1 
     a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2 
     c = 2 * asin(sqrt(a)) 
     km = 6367 * c 
     return km 
+0

, какой столбец следует использовать для заказа? –

+0

@vkp: DataFrame уже заказывается StartTime. Поэтому мне нужно найти расстояние между первой записью и каждой другой записью в группе. – user3447653

ответ

4

Попробуйте ниже

#standardSQL 
CREATE TEMPORARY FUNCTION distance(lat1 FLOAT64, lon1 FLOAT64, lat2 FLOAT64, lon2 FLOAT64) 
RETURNS FLOAT64 AS ((
WITH constants AS (
    SELECT 0.017453292519943295 AS p 
) 
SELECT 12742 * ASIN(SQRT(
    0.5 - COS((lat2 - lat1) * p)/2 + 
    COS(lat1 * p) * COS(lat2 * p) * 
    (1 - COS((lon2 - lon1) * p))/2)) 
FROM constants 
)); 

WITH YourTable AS (
    SELECT 1 AS Row, 71 AS Id1, 34 AS Id2, '2016-11-21 00:41:05 UTC' AS StartTime, '2016-11-21 00:47:06 UTC' AS StopTime, 33.6008949 AS Latitude, -83.83803 AS Longitude, '2016-11-21 00:43:42 UTC' AS DateTime UNION ALL  
    SELECT 2 AS Row, 71 AS Id1, 44 AS Id2, '2016-11-21 00:54:55 UTC' AS StartTime, '2016-11-21 00:56:28 UTC' AS StopTime, 33.604248 AS Latitude, -83.86729 AS Longitude, '2016-11-21 00:55:18 UTC' AS DateTime UNION ALL  
    SELECT 3 AS Row, 71 AS Id1, 45 AS Id2, '2016-11-21 02:08:17 UTC' AS StartTime, '2016-11-21 02:09:52 UTC' AS StopTime, 33.60586 AS Latitude, -83.8711 AS Longitude, '2016-11-21 02:09:03 UTC' AS DateTime UNION ALL  
    SELECT 4 AS Row, 71 AS Id1, 67 AS Id2, '2016-11-21 02:16:02 UTC' AS StartTime, '2016-11-21 02:17:21 UTC' AS StopTime, 33.6043777 AS Latitude, -83.86624 AS Longitude, '2016-11-21 02:16:28 UTC' AS DateTime 
) 
SELECT *, 
    distance(Latitude, Longitude, FIRST_VALUE(Latitude) OVER(PARTITION BY Id1 ORDER BY Id2), FIRST_VALUE(Longitude) OVER(PARTITION BY Id1 ORDER BY Id2)) AS dist 
FROM YourTable 
ORDER BY Id1, Id2 
+0

Если это нужно выполнить в консоли BigQuery. Я попробовал это из ноутбука, но это порождает ошибку при создании временных функций. – user3447653

+0

, чтобы проверить выше - начните с веб-интерфейса –