簡體   English   中英

PySpark:如何將 Python UDF 應用於 PySpark DataFrame 列?

[英]PySpark: How to apply a Python UDF to PySpark DataFrame columns?

我有一個帶有兩組緯度、經度坐標的 PySpark DataFrame。 我正在嘗試計算給定行的每組坐標之間的 Haversine 距離。 我正在使用我在網上找到的以下haversine() 問題是它不能應用於列,或者至少我不知道這樣做的語法。 有人可以分享語法或指出更好的解決方案嗎?

from math import radians, cos, sin, asin, sqrt

def haversine(lat1, lon1, lat2, lon2):
    """
    Calculate the great circle distance between two points 
    on the earth (specified in decimal degrees)
    """
    # convert decimal degrees to radians 
    lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
    # haversine formula 
    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
    c = 2 * asin(sqrt(a)) 
    # Radius of earth in miles is 3,963; 5280 ft in 1 mile
    ft = 3963 * 5280 * c
    return ft

我知道上面的haversine()函數有效,因為我使用數據幀中的一些緯度/經度坐標對其進行了測試,並得到了合理的結果:

haversine(-85.8059, 38.250134, 
          -85.805122, 38.250098)
284.1302325439314

當我用 PySpark 數據框中的經緯度對應的列名替換樣本坐標時,出現錯誤。 我嘗試了以下代碼以嘗試創建一個新列,其中包含以英尺為單位的計算出的 Haversine 距離:

df.select('id', 'p1_longitude', 'p1_latitude', 'p2_lon', 'p2_lat').withColumn('haversine_dist', 
                           haversine(df['p1_latitude'],
                                    df['p1_longitude'],
                                    df['p2_lat'],
                                    df['p2_lon']))
.show()

但我收到錯誤:

必須是實數,而不是列回溯(最近一次調用最后一次):
文件“”,第 8 行,在半正弦中 TypeError: must be real number, not Column

這向我表明我必須以某種方式迭代地將我的半正弦函數應用於我的 PySpark DataFrame 的每一行,但我不確定這個猜測是否正確,即使是這樣,我也不知道該怎么做。 順便說一句,我的緯度/經度是浮動類型。

如果可以使用 Spark 內置函數,請不要使用 UDF,因為它們的性能通常較低。

這是一個僅使用與您的函數相同的 Spark SQL 函數的解決方案:

from pyspark.sql.functions import col, radians, asin, sin, sqrt, cos

df.withColumn("dlon", radians(col("p2_lon")) - radians(col("p1_longitude"))) \
  .withColumn("dlat", radians(col("p2_lat")) - radians(col("p1_latitude"))) \
  .withColumn("haversine_dist", asin(sqrt(
                                         sin(col("dlat") / 2) ** 2 + cos(radians(col("p1_latitude")))
                                         * cos(radians(col("p2_lat"))) * sin(col("dlon") / 2) ** 2
                                         )
                                    ) * 2 * 3963 * 5280) \
  .drop("dlon", "dlat")\
  .show(truncate=False)

給出:

+-----------+------------+----------+---------+------------------+
|p1_latitude|p1_longitude|p2_lat    |p2_lon   |haversine_dist    |
+-----------+------------+----------+---------+------------------+
|-85.8059   |38.250134   |-85.805122|38.250098|284.13023254857814|
+-----------+------------+----------+---------+------------------+

您可以在此處找到可用的 Spark 內置函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM