如何使用(Py)Spark汇总数据集中数据点之间的距离?

And*_*ruz 0 apache-spark apache-spark-sql pyspark

我有一个时间段内用户的Lat/Lon格式的位置数据集.我想计算这些用户旅行的距离.样本数据集:

| 时间戳| 用户| 纬度|经度| | 1462838468 | 49B4361512443A4DA ... | 39.777982 | -7.054599 | | 1462838512 | 49B4361512443A4DA ... | 39.777982 | -7.054599 | | 1462838389 | 49B4361512443A4DA ... | 39.777982 | -7.054599 | | 1462838497 | 49B4361512443A4DA ... | 39.777982 | -7.054599 | | 1465975885 | 6E9E0581E2A032FD8 ... | 37.118362 | -8.205041 | | 1457723815 | 405C238E25FE0B9E7 ... | 37.177322 | -7.426781 | | 1457897289 | 405C238E25FE0B9E7 ... | 37.177922 | -7.447443 | | 1457899229 | 405C238E25FE0B9E7 ... | 37.177922 | -7.447443 | | 1457972626 | 405C238E25FE0B9E7 ... | 37.18059 | -7.46128 | | 1458062553 | 405C238E25FE0B9E7 ... | 37.177322 | -7.426781 | | 1458241825 | 405C238E25FE0B9E7 ... | 37.178172 | -7.444512 | | 1458244457 | 405C238E25FE0B9E7 ... | 37.178172 | -7.444512 | | 1458412513 | 405C238E25FE0B9E7 ... | 37.177322 | -7.426781 | | 1458412292 | 405C238E25FE0B9E7 ... | 37.177322 | -7.426781 | | 1465197963 | 6E9E0581E2A032FD8 ... | 37.118362 | -8.205041 | | 1465202192 | 6E9E0581E2A032FD8 ... | 37.118362 | -8.205041 | | 1465923817 | 6E9E0581E2A032FD8 ... | 37.118362 | -8.205041 | | 1465923766 | 6E9E0581E2A032FD8 ... | 37.118362 | -8.205041 | | 1465923748 | 6E9E0581E2A032FD8 ... | 37.118362 | -8.205041 | | 1465923922 | 6E9E0581E2A032FD8 ... | 37.118362 | -8.205041 |

我曾想过使用自定义聚合器函数,但似乎没有Python支持.此外,操作需要按特定顺序在相邻点上完成,因此我不知道自定义聚合器是否可行.

我也看了一下,reduceByKey但距离函数似乎没有满足操作员的要求.

有没有办法在Spark中以有效的方式执行此操作?

zer*_*323 9

它看起来像窗口函数的工作.假设我们将距离定义为:

from pyspark.sql.functions import acos, cos, sin, lit, toRadians

def dist(long_x, lat_x, long_y, lat_y):
    return acos(
        sin(toRadians(lat_x)) * sin(toRadians(lat_y)) + 
        cos(toRadians(lat_x)) * cos(toRadians(lat_y)) * 
            cos(toRadians(long_x) - toRadians(long_y))
    ) * lit(6371.0)
Run Code Online (Sandbox Code Playgroud)

您可以将窗口定义为:

from pyspark.sql.window import Window

w = Window().partitionBy("User").orderBy("Timestamp")
Run Code Online (Sandbox Code Playgroud)

并计算连续观测之间的距离lag:

from pyspark.sql.functions import lag

df.withColumn("dist", dist(
    "longitude", "latitude",
    lag("longitude", 1).over(w), lag("latitude", 1).over(w)
).alias("dist"))
Run Code Online (Sandbox Code Playgroud)

之后,您可以执行标准聚合.