PySpark:计算的条件连接

时间:2017-03-23 13:36:36

标签: join apache-spark pyspark spark-dataframe

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

  

Py4JJavaError:调用o341.join时发生错误。 :   java.lang.RuntimeException:无效的PythonUDF   PythonUDF#(北纬#1655#经度1657年LNG#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)

禁用的功能withColumn工作正常。但条件连接引发了上面的错误。知道怎么解决这个问题吗?

0 个答案:

没有答案