Spark 1.6以空值爆炸[重复]

Posted

技术标签:

【中文标题】Spark 1.6以空值爆炸[重复]【英文标题】:Spark 1.6 explode with null values [duplicate] 【发布时间】:2017-10-20 15:49:44 【问题描述】:

我有一个要展平的数据框。作为该过程的一部分,我想分解它,所以如果我有一列数组,数组的每个值将用于创建一个单独的行。我知道我可以使用分解函数。但是,我有一个问题,该列包含空值,我使用 spark 1.6。这是数据类型和我想要的示例: 我的数据:

id | ListOfRficAction| RficActionAttachment
_______________________________
1  | Luke            | [baseball, soccer]
2  | Lucy            | null

我想要

id | ListOfRficAction| RficActionAttachment
_______________________________
1  | Luke            | baseball
1  | Luke            | soccer
2  | Lucy            | null

我使用的是 Spark 1.6(所以我不能使用explode_outer 函数)并且我尝试使用explode 但我有以下错误:

 scala.MatchError: [null] (of class org.apache.spark.sql.catalyst.expressions.GenericRowWithSchema)

我也试试:

df.withColumn("likes", explode(
  when(col("likes").isNotNull, col("likes"))
    // If null explode an array<string> with a single null
    .otherwise(array(lit(null).cast("string")))))

但我的 DataFrame 架构非常复杂(我有字符串和长字符串),所以转换函数不起作用。这是我的架构的一部分和我遇到的错误:

 |-- RficActionAttachment: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- ActivityFileAutoUpdFlg: string (nullable = true)
 |    |    |-- ActivityFileDate: string (nullable = true)
 |    |    |-- ActivityFileDeferFlg: string (nullable = true)
 |    |    |-- ActivityFileDockReqFlg: string (nullable = true)
 |    |    |-- ActivityFileDockStatFlg: string (nullable = true)
 |    |    |-- ActivityFileExt: string (nullable = true)
 |    |    |-- ActivityFileName: string (nullable = true)
 |    |    |-- ActivityFileRev: string (nullable = true)
 |    |    |-- ActivityFileSize: long (nullable = true)
 |    |    |-- ActivityFileSrcPath: string (nullable = true)
 |    |    |-- ActivityFileSrcType: string (nullable = true)
 |    |    |-- ActivityId: string (nullable = true)
 |    |    |-- AttachmentId: string (nullable = true)
 |    |    |-- Comment: string (nullable = true)

用户类抛出异常:

org.apache.spark.sql.AnalysisException: cannot resolve 'CASE WHEN isnotnull(ListOfRficAction.RficAction.ListOfRficActionAttachment.RficActionAttachment) THEN ListOfRficAction.RficAction.ListOfRficActionAttachment.RficActionAttachment ELSE array(ListOfRficAction.RficAction.ListOfRficActionAttachment.RficActionAttachment)' 

由于数据类型不匹配:THEN 和 ELSE 表达式应该都是相同类型或强制转换为通用类型;

知道我能做什么吗?

【问题讨论】:

我的问题有所不同,因为我在使用我的架构时无法使用案例 问题是这种情况对我不起作用 【参考方案1】:

首先将array(null)列中的所有null值替换为array(null),然后使用explode。使用问题中的示例数据框:

val df = Seq((1, "Luke", Array("baseball", "soccer")), (2, "Lucy", null))
  .toDF("id", "ListOfRficAction", "RficActionAttachment")

df.withColumn("RficActionAttachment", 
    when($"RficActionAttachment".isNull, array(lit(null)))
    .otherwise($"RficActionAttachment"))
  .withColumn("RficActionAttachment", explode($"RficActionAttachment"))

这将给出请求的结果:

+---+----------------+--------------------+
| id|ListOfRficAction|RficActionAttachment|
+---+----------------+--------------------+
|  1|            Luke|            baseball|
|  1|            Luke|              soccer|
|  2|            Lucy|                null|
+---+----------------+--------------------+

【讨论】:

谢谢@Shaido 的回答,但正如我所说,我尝试了这个,我仍然有同样的错误:无法解决'CASE WHEN isnull(ListOfRficAction.RficAction.ListOfRficActionAttachment.RficActionAttachment) THEN array(null) ELSE ListOfRficAction.RficAction.ListOfRficActionAttachment.RficActionAttachment' 可能是由于我的数据框架构 @MbulaGuyMarcel 数据框模式应该没关系,如果你有一个数组,上面应该可以工作。对代码做了一个小更新,你能再试一次吗? 对不起,它不起作用 这是我的 DF : *********************************isAttachment +-- ------+--------------------+---------- ----+ |资产ID| ListOfRficAction|ListOfRficActionAttachment| +--------+--------------------------------+-------- -------+ |1-KTOUUY|[WrappedArray([2,...| null| |1-KTOUUY|[WrappedArray([2,...| [WrappedArray([Y,...| +--------+--------------------------------+-------- -------+ 我尝试将 ListOfRficActionAttachment 变平 @MbulaGuyMarcel 从您的错误消息中,看起来上面代码中的 .otherwise($"RficActionAttachment") 部分没有提供数组。有必要像上面的代码那样分两个阶段进行。您也可以尝试使用 `df.withColumn("RficActionAttachment", explode_outer($"RficActionAttachment"))` 来达到同样的效果。

以上是关于Spark 1.6以空值爆炸[重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何使用scala在Apache spark中用空字符串(“”)替换空值[重复]

PYSPARK:-在数据框中爆炸数组而不丢失空值:'DataFrame'对象没有属性'_get_object_id'

将嵌套的空值转换为数据框火花内的空字符串

Spark fillNa 不替换空值

Spark DataFrame 空值到数据集

如何在 Spark/Scala 中查找具有许多空值的列