gpt4 book ai didi

java - Spark sql如何在不丢失空值的情况下爆炸

转载 作者:IT老高 更新时间:2023-10-28 21:14:20 24 4
gpt4 key购买 nike

我有一个要展平的数据框。作为该过程的一部分,我想将其分解,因此如果我有一列数组,则数组的每个值都将用于创建单独的行。例如,

id | name | likes
_______________________________
1 | Luke | [baseball, soccer]

应该变成

id | name | likes
_______________________________
1 | Luke | baseball
1 | Luke | soccer

这是我的代码

private DataFrame explodeDataFrame(DataFrame df) {
DataFrame resultDf = df;
for (StructField field : df.schema().fields()) {
if (field.dataType() instanceof ArrayType) {
resultDf = resultDf.withColumn(field.name(), org.apache.spark.sql.functions.explode(resultDf.col(field.name())));
resultDf.show();
}
}
return resultDf;
}

问题是在我的数据中,一些数组列有空值。在这种情况下,将删除整行。所以这个数据框:

id | name | likes
_______________________________
1 | Luke | [baseball, soccer]
2 | Lucy | null

变成

id | name | likes
_______________________________
1 | Luke | baseball
1 | Luke | soccer

而不是

id | name | likes
_______________________________
1 | Luke | baseball
1 | Luke | soccer
2 | Lucy | null

如何分解我的数组,以免丢失空行?

我正在使用 Spark 1.5.2 和 Java 8

最佳答案

Spark 2.2+

你可以使用explode_outer函数:

import org.apache.spark.sql.functions.explode_outer

df.withColumn("likes", explode_outer($"likes")).show

// +---+----+--------+
// | id|name| likes|
// +---+----+--------+
// | 1|Luke|baseball|
// | 1|Luke| soccer|
// | 2|Lucy| null|
// +---+----+--------+

Spark <= 2.1

在 Scala 中,但 Java 等效项应该几乎相同(要导入单个函数,请使用 import static)。

import org.apache.spark.sql.functions.{array, col, explode, lit, when}

val df = Seq(
(1, "Luke", Some(Array("baseball", "soccer"))),
(2, "Lucy", None)
).toDF("id", "name", "likes")

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")))))

这里的想法基本上是将 NULL 替换为所需类型的 array(NULL)。对于复杂类型(又名 structs),您必须提供完整的模式:

val dfStruct = Seq((1L, Some(Array((1, "a")))), (2L, None)).toDF("x", "y")

val st = StructType(Seq(
StructField("_1", IntegerType, false), StructField("_2", StringType, true)
))

dfStruct.withColumn("y", explode(
when(col("y").isNotNull, col("y"))
.otherwise(array(lit(null).cast(st)))))

dfStruct.withColumn("y", explode(
when(col("y").isNotNull, col("y"))
.otherwise(array(lit(null).cast("struct<_1:int,_2:string>")))))

注意:

如果已创建数组 ColumncontainsNull 设置为 false,则应首先更改此设置(使用 Spark 2.1 测试):

df.withColumn("array_column", $"array_column".cast(ArrayType(SomeType, true)))

关于java - Spark sql如何在不丢失空值的情况下爆炸,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39739072/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com