我是pyspark的新手,我正在尝试使用udf映射一些字符串名称。我必须将一些数据值映射到新名称,因此我要从sparkdf发送列值,并将映射字段的字典发送到udf,而不是在{{1}之后写大量.when()
}。
尝试仅将2个字符串传递给udf,并且可以,但是不传递字典。
.withColumn()
但是不存在关于方法col()的此错误。有什么想法吗?:
def stringToStr_function(checkCol, dict1) :
for key, value in dict1.iteritems() :
if(checkCol != None and checkCol==key): return value
stringToStr_udf = udf(stringToStr_function, StringType())
df = sparkdf.toDF().withColumn(
"new_col",
stringToStr_udf(
lit("REQUEST"),
{"REQUEST": "Requested", "CONFIRM": "Confirmed", "CANCEL": "Cancelled"}
)
)
感谢您的帮助。我正在使用aws胶和Python 2.x,并且正在笔记本中进行测试。
答案 0 :(得分:0)
如linked duplicate所示:
最干净的解决方案是使用闭包传递其他参数
但是,对于此特定问题,您不需要udf
。 (请参见Spark functions vs UDF performance?)
您可以使用pyspark.sql.functions.when
来实现IF-THEN-ELSE
logic:
from pyspark.sql.functions import coalesce, col, lit, when
def stringToStr_function(checkCol, dict1):
return coalesce(
*[when(col(checkCol) == key, lit(value)) for key, value in dict1.iteritems()]
)
df = sparkdf.withColumn(
"new_col",
stringToStr_function(
checkCol = lit("REQUEST"),
dict1 = {"REQUEST": "Requested", "CONFIRM": "Confirmed", "CANCEL": "Cancelled"}
)
)
如果when
中的值与value
相匹配,我们将遍历字典中的项目并使用checkCol
返回key
。将其包装到对pyspark.sql.functions.coalesce()
的调用中,该调用将返回第一个非空值。
答案 1 :(得分:0)
以下是使用UDF和广播词典解决此问题的方法。 pault的解决方案很聪明,并且似乎依赖于字典的自动广播,因为它很小。不要认为pault的解决方案适用于大于自动广播限制的字典。在我看来,广播是编写PySpark代码的最安全方法。如果无法使用本机Spark函数来表达逻辑,则UDF方法也可能会更好。
假设您具有以下DataFrame。
+-------+
| status|
+-------+
|REQUEST|
|CONFIRM|
+-------+
这是将映射字典应用于列的代码。
def stringToStr(dict1_broadcasted):
def f(x):
return dict1_broadcasted.value.get(x)
return F.udf(f)
df = spark.createDataFrame([["REQUEST",], ["CONFIRM",]]).toDF("status")
b = spark.sparkContext.broadcast({"REQUEST": "Requested", "CONFIRM": "Confirmed", "CANCEL": "Cancelled"})
df.withColumn(
"new_col",
stringToStr(b)(F.col("status"))
).show()
+-------+---------+
| status| new_col|
+-------+---------+
|REQUEST|Requested|
|CONFIRM|Confirmed|
+-------+---------+
有关广播PySpark词典时可能遇到的所有错误的更多详细信息,请参见this post。很难做到正确,但却是工具包中拥有的强大技术。