Rap*_*oth 10 scala apache-spark
由于镶木地板解析空数组的事实,我在写表之前将空数组替换为null.现在,当我阅读表格时,我想做相反的事情:
我有一个具有以下架构的DataFrame:
|-- id: long (nullable = false)
|-- arr: array (nullable = true)
| |-- element: struct (containsNull = true)
| | |-- x: double (nullable = true)
| | |-- y: double (nullable = true)
Run Code Online (Sandbox Code Playgroud)
以及以下内容:
+---+-----------+
| id| arr|
+---+-----------+
| 1|[[1.0,2.0]]|
| 2| null|
+---+-----------+
Run Code Online (Sandbox Code Playgroud)
我想用空数组替换null数组(id = 2),即
+---+-----------+
| id| arr|
+---+-----------+
| 1|[[1.0,2.0]]|
| 2| []|
+---+-----------+
Run Code Online (Sandbox Code Playgroud)
我试过了:
val arrSchema = df.schema(1).dataType
df
.withColumn("arr",when($"arr".isNull,array().cast(arrSchema)).otherwise($"arr"))
.show()
Run Code Online (Sandbox Code Playgroud)
这使 :
java.lang.ClassCastException:org.apache.spark.sql.types.NullType $无法强制转换为org.apache.spark.sql.types.StructType
编辑:我不想"硬编码"我的数组列的任何模式(至少不是结构的模式),因为这可能因情况而异.我只能df
在运行时使用架构信息
我顺便使用Spark 2.1,因此我无法使用 typedLit
具有已知外部类型的Spark 2.2+
通常,您可以使用typedLit
提供空数组。
import org.apache.spark.sql.functions.typedLit
typedLit(Seq.empty[(Double, Double)])
Run Code Online (Sandbox Code Playgroud)
要将特定名称用于嵌套对象,可以使用案例类:
case class Item(x: Double, y: Double)
typedLit(Seq.empty[Item])
Run Code Online (Sandbox Code Playgroud)
或通过演员重命名:
typedLit(Seq.empty[(Double, Double)])
.cast("array<struct<x: Double, y: Double>>")
Run Code Online (Sandbox Code Playgroud)仅使用架构的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")
Run Code Online (Sandbox Code Playgroud)
schema
可以从现有位置提取DataFrame
并附加其他内容StructType
:
StructType(Seq(
StructField("arr", df.schema("arr").dataType)
))
Run Code Online (Sandbox Code Playgroud)一种方法是使用 UDF :
val arrSchema = df.schema(1).dataType // ArrayType(StructType(StructField(x,DoubleType,true), StructField(y,DoubleType,true)),true)
val emptyArr = udf(() => Seq.empty[Any],arrSchema)
df
.withColumn("arr",when($"arr".isNull,emptyArr()).otherwise($"arr"))
.show()
+---+-----------+
| id| arr|
+---+-----------+
| 1|[[1.0,2.0]]|
| 2| []|
+---+-----------+
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2745 次 |
最近记录: |