我试图先打印一个数据帧的计数,然后打印它的前几行,然后再将其发送出去进行进一步处理。
奇怪的是,在调用count()
之后,数据帧为空。
val modifiedDF = funcA(sparkDF)
val deltaDF = modifiedDF.except(sparkDF)
println(deltaDF.count()) // prints 10
println(deltaDF.count()) //prints 0, similar behavior with show
funcB(deltaDF) //gets null dataframe
我能够使用deltaDF.collect.foreach(println)
和随后对count
的调用来验证相同的内容。
但是,如果我不打电话给count
或show
,而是直接发送它,funcB
将获得10行的整个DF。
是预期的吗?
funcA()
的定义及其依赖性:
def funcA(inputDataframe: DataFrame): DataFrame = {
val col_name = "colA"
val modified_df = inputDataframe.withColumn(col_name, customUDF(col(col_name)))
val modifiedDFRaw = modified_df.limit(10)
modifiedDFRaw.withColumn("colA", modifiedDFRaw.col("colA").cast("decimal(38,10)"))
}
val customUDF = udf[Option[java.math.BigDecimal], java.math.BigDecimal](myUDF)
def myUDF(sval: java.math.BigDecimal): Option[java.math.BigDecimal] = {
val strg_name = Option(sval).getOrElse(return None)
if (change_cnt < 20) {
change_cnt = change_cnt + 1
Some(strg_name.multiply(new java.math.BigDecimal("1000")))
} else {
Some(strg_name)
}
}
答案 0 :(得分:1)
首先,用作UserDefinedFunction
的函数必须至少是幂等的,但必须是纯函数。否则,结果将是不确定的。尽管在最新版本中提供了一些逃生功能(可能会提示Spark不应该重新执行该功能),但这些操作在这里没有帮助。
此外,它具有可变的稳定性(尚不清楚change_cnt
的来源是什么,但是它是在udf
中写入和读取的),只是行不通-Spark doesn't provide global mutable state
总体代码:
不幸的是,这两个组成部分都无法挽救。您必须回到计划阶段并重新考虑您的设计。
答案 1 :(得分:0)
您的数据框是一个分布式数据集,由于每个节点中的count()可能不同,因此尝试执行count()会返回不可预测的结果。阅读下面有关RDD的文档。它也适用于DataFrame。
https://spark.apache.org/docs/2.3.0/rdd-programming-guide.html#understanding-closures- https://spark.apache.org/docs/2.3.0/rdd-programming-guide.html#printing-elements-of-an-rdd