Skip to main content
 首页 » 编程设计

python之自连接后使用 UDF 的 Spark 2.0 过滤器

2024年10月17日29xxx_UU

我需要使用我自己的用户定义函数来过滤 Spark 数据帧。我的数据框是使用 jdbc 连接从数据库中读取的,然后在过滤之前在 spark 中进行自连接操作。尝试收集过滤器后的数据帧时发生错误。

我已经在 spark 1.6 中成功地使用了它。然而,在昨天升级到 2.0 后,它失败并出现错误:

py4j.protocol.Py4JJavaError: An error occurred while calling o400.collectToPython. 
: java.lang.UnsupportedOperationException: Cannot evaluate expression:  
<lambda>(input[0, string, true]) 

这是一个产生错误的最小示例(在我的环境中):

from pyspark.sql.functions import udf, col 
from pyspark.sql.types import BooleanType 
 
spark = SparkSession.builder.master('local').appName('test').getOrCreate() 
 
# this works successfully 
df = spark.createDataFrame([('Alice', 1), ('Bob', 2), ('Dan', None)],  
                           ['name', 'age']) 
df.filter(udf(lambda x: 'i' in x, BooleanType())(df.name)).collect() 
>>> [Row(name=u'Alice', age=1)] 
 
# this produces the error 
df_emp = spark.createDataFrame([(1, 'Alice', None), (2, 'Bob', 1),  
                                (3, 'Dan', 2), (4, 'Joe', 2)],  
                               ['id', 'name', 'manager_id']) 
df1 = df_emp.alias('df1') 
df2 = df_emp.alias('df2') 
cols = df1.columns 
# the self-join 
result = df1.join(df2, col('df1.id') == col('df2.manager_id'), 'left_outer') 
result.collect() 
>>> [Row(id=1, name=u'Alice', manager_id=None),  
     Row(id=3, name=u'Dan', manager_id=2), Row(id=2, name=u'Bob', manager_id=1),  
     Row(id=2, name=u'Bob', manager_id=1), Row(id=4, name=u'Joe', manager_id=2)] 
 
# simple udf filter 
filtered = result.filter(udf(lambda x: 'i' in x, BooleanType())(result.name)) 
filtered.collect() 
# the above error is produced... 

在这种情况下我做错了什么吗?这是 2.0 中的错误还是我应该考虑两个版本之间的一些行为变化?

请您参考如下方法:

这是 pyspark 中的错误。

我在这里提交了一个错误 https://issues.apache.org/jira/browse/SPARK-17100

此问题出现在 left_outer、right_outer 和外连接中,但不会出现在内部连接中。

一种解决方法是在过滤器之前缓存连接结果。

例如:

result = df1.join(df2, col('df1.id') == col('df2.manager_id'), 'left_outer').select(df2.name).cache()