Join PySpark:计算时的条件联接

Join PySpark:计算时的条件联接,join,apache-spark,pyspark,spark-dataframe,Join,Apache Spark,Pyspark,Spark Dataframe,我得到了一个数据框,其中包含位置及其GPS坐标(如经度和纬度)。现在我想找到距离另一个500米的位置。因此,我尝试将数据帧本身连接起来,但不是进行完全连接,而是仅针对满足条件的那些值,从而减少整体连接。但我得到了这个错误: Py4JJavaError:调用o341.join时出错: java.lang.RuntimeException:PythonUDF无效 蟒蛇(纬度1655,经度1657,液化天然气1665,有限公司1666), 需要来自多个子级的属性 你知道怎么解决吗?我知道可以根据列的值

我得到了一个数据框,其中包含位置及其GPS坐标(如经度和纬度)。现在我想找到距离另一个500米的位置。因此,我尝试将数据帧本身连接起来,但不是进行完全连接,而是仅针对满足条件的那些值,从而减少整体连接。但我得到了这个错误:

Py4JJavaError:调用o341.join时出错: java.lang.RuntimeException:PythonUDF无效 蟒蛇(纬度1655,经度1657,液化天然气1665,有限公司1666), 需要来自多个子级的属性

你知道怎么解决吗?我知道可以根据列的值进行条件联接。但我需要它基于一个需要4列值的计算

以下是我所做的:

原始数据帧如下所示:

df
 |-- listing_id: integer (nullable = true)
 |-- latitude: float (nullable = true)
 |-- longitude: float (nullable = true)
 |-- price: integer (nullable = true)
 |-- street_address: string (nullable = true)
在重命名某些列时,我将从中创建一个副本。这是一个先决条件,因为联接操作不喜欢同名的两列

df2 = df.select(df.listing_id.alias('id'), 
                df.street_address.alias('address'),
                df.longitude.alias('lng'),
                df.latitude.alias('ltd'),
                df.price.alias('prc')
               )
然后我得到了哈弗森函数,它计算了两个地理位置之间的距离,单位为公制公里:

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

def haversine(lon1, lat1, lon2, lat2):

    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)) 
    r = 6371 # Radius of earth in kilometers. Use 3956 for miles
    return c * r
这就是我想应用于条件联接的函数:

from pyspark.sql.types import *
from pyspark.sql.functions import udf, col

#berlin_lng = 13.41053
#berlin_ltd = 52.52437

#hav_distance_udf = udf(lambda lng1, ltd1: haversine(lng1, ltd1, berlin_lng, berlin_ltd), FloatType())
#df3 = df.withColumn("distance_berlin", hav_distance_udf(df.longitude, df.latitude))

hav_distance_udf = udf(lambda lng1, ltd1, lng2, ltd2: haversine(lng1, ltd1, lng2, ltd2), FloatType())

in_range = hav_distance_udf(col('latitude'), col('longitude'), col('lng'), col('ltd')) > 0.5

df3 = df.join(df2, in_range)

带列的禁用功能工作正常。但是条件连接会引发错误,请参见上文。知道怎么解决吗?

啊,又是零。所以我需要更新我的Spark安装?至少是补丁。好的,需要和我的IT管理员谈谈。但是你认为这个条件连接是一个好的解决方案吗?或者你会提出另一个解决方案吗?这是一个非常低效的解决方案,原因有很多(至少想到两个)。通过跳过udf,您可以做得更好一些(例如,请参见),作为奖励,您不需要升级集群,但要获得合理的改进,您需要比这更聪明(并且可能接受一些近似值)。