由于实木复合地板无法解析空数组,因此在写表之前我将空数组替换为null。现在,当我阅读表格时,我想做相反的事情:
我有一个具有以下架构的DataFrame:
|-- id: long (nullable = false)
|-- arr: array (nullable = true)
| |-- element: struct (containsNull = true)
| | |-- x: double (nullable = true)
| | |-- y: double (nullable = true)
以及以下内容:
+---+-----------+
| id| arr|
+---+-----------+
| 1|[[1.0,2.0]]|
| 2| null|
+---+-----------+
我想将空数组(id = 2)替换为空数组,即
+---+-----------+
| id| arr|
+---+-----------+
| 1|[[1.0,2.0]]|
| 2| []|
+---+-----------+
我尝试过:
val arrSchema = df.schema(1).dataType
df
.withColumn("arr",when($"arr".isNull,array().cast(arrSchema)).otherwise($"arr"))
.show()
给出:
java.lang.ClassCastException:org.apache.spark.sql.types.NullType $ 无法转换为org.apache.spark.sql.types.StructType
编辑:我不想对数组列的任何模式(至少不是结构的模式)进行“硬编码”,因为这可能因情况而异。我只能在运行时使用来自df
的架构信息
我正在使用Spark 2.1,因此无法使用typedLit
答案 0 :(得分:3)
Spark 2.2 +
通常,您可以使用typedLit
提供空数组。
import org.apache.spark.sql.functions.typedLit
typedLit(Seq.empty[(Double, Double)])
要对嵌套对象使用特定的名称,可以使用案例类:
case class Item(x: Double, y: Double)
typedLit(Seq.empty[Item])
typedLit(Seq.empty[(Double, Double)])
.cast("array<struct<x: Double, y: Double>>")
仅具有架构的Spark 2.1 +
仅使用架构,您可以尝试:
val schema = StructType(Seq(
StructField("arr", StructType(Seq(
StructField("x", DoubleType),
StructField("y", DoubleType)
)))
))
def arrayOfSchema(schema: StructType) =
from_json(lit("""{"arr": []}"""), schema)("arr")
arrayOfSchema(schema).alias("arr")
其中schema
可以从现有的DataFrame
中提取并用其他StructType
包装:
StructType(Seq(
StructField("arr", df.schema("arr").dataType)
))
答案 1 :(得分:1)
一种方法是使用UDF:
var a = document.createElement('a');
a.textContent = "Visit this store"
a.href = "/bottle.php?id=" + id;
infowincontent.appendChild(a);
答案 2 :(得分:1)
另一种方法是使用coalesce
:
val df = Seq(
(Some(1), Some(Array((1.0, 2.0)))),
(Some(2), None)
).toDF("id", "arr")
df.withColumn("arr", coalesce($"arr", typedLit(Array.empty[(Double, Double)]))).
show
// +---+-----------+
// | id| arr|
// +---+-----------+
// | 1|[[1.0,2.0]]|
// | 2| []|
// +---+-----------+
答案 3 :(得分:0)
带有案例类的UDF也可能很有趣:
case class Item(x: Double, y: Double)
val udf_emptyArr = udf(() => Seq[Item]())
df
.withColumn("arr",coalesce($"arr",udf_emptyArr()))
.show()