我得到的数据框包含位置及其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工作正常。但条件连接引发了上面的错误。知道怎么解决这个问题吗?