scala - 使用定义的 StructType 转换 Spark 数据帧的值
问题描述
有没有办法使用 StructType 转换数据框的所有值?
让我用一个例子来解释我的问题:
假设我们在从文件读取后获得了一个数据帧(我提供了一个生成此数据帧的代码,但在我的真实世界项目中,我在从文件读取后获得了这个数据帧):
import org.apache.spark.sql.{Row, SparkSession}
import org.apache.spark.sql.types._
import org.apache.spark.sql.functions._
import spark.implicits._
val rows1 = Seq(
Row("1", Row("a", "b"), "8.00", Row("1","2")),
Row("2", Row("c", "d"), "9.00", Row("3","4"))
)
val rows1Rdd = spark.sparkContext.parallelize(rows1, 4)
val schema1 = StructType(
Seq(
StructField("id", StringType, true),
StructField("s1", StructType(
Seq(
StructField("x", StringType, true),
StructField("y", StringType, true)
)
), true),
StructField("d", StringType, true),
StructField("s2", StructType(
Seq(
StructField("u", StringType, true),
StructField("v", StringType, true)
)
), true)
)
)
val df1 = spark.createDataFrame(rows1Rdd, schema1)
println("Schema with nested struct")
df1.printSchema()
root
|-- id: string (nullable = true)
|-- s1: struct (nullable = true)
| |-- x: string (nullable = true)
| |-- y: string (nullable = true)
|-- d: string (nullable = true)
|-- s2: struct (nullable = true)
| |-- u: string (nullable = true)
| |-- v: string (nullable = true)
现在假设我的客户向我提供了他想要的数据架构(相当于读取数据帧的架构,但具有不同的数据类型(包含 StringTypes、IntegerTypes ...)):
val wantedSchema = StructType(
Seq(
StructField("id", IntegerType, true),
StructField("s1", StructType(
Seq(
StructField("x", StringType, true),
StructField("y", StringType, true)
)
), true),
StructField("d", DoubleType, true),
StructField("s2", StructType(
Seq(
StructField("u", IntegerType, true),
StructField("v", IntegerType, true)
)
), true)
)
)
使用提供的 StructType 转换数据框值的最佳方法是什么?
如果有一种方法可以应用于数据帧,那就太好了,它通过自己转换所有值来应用新的 StructTypes。
PS:这是一个用作示例的小型数据框,在我的项目中,数据框包含更多行。如果它是一个包含几列的小型 Dataframe,我可以轻松完成转换,但就我而言,我正在寻找一种智能解决方案,通过应用 StructType 来转换所有值,而无需手动转换每个列/值编码。
我将不胜感激您能提供的任何帮助,非常感谢!
解决方案
经过大量研究,这里有一个通用的解决方案,可以按照模式转换数据框:
val castedDf = df1.selectExpr(wantedSchema.map(
field => s"CAST ( ${field.name} As ${field.dataType.sql}) ${field.name}"
): _*)
这是铸造数据框的架构:
castedDf.printSchema
root
|-- id: integer (nullable = true)
|-- s1: struct (nullable = true)
| |-- x: string (nullable = true)
| |-- y: string (nullable = true)
|-- d: double (nullable = true)
|-- s2: struct (nullable = true)
| |-- u: integer (nullable = true)
| |-- v: integer (nullable = true)
我希望它能对某人有所帮助,我花了 5 天时间寻找这个简单/通用的解决方案。
推荐阅读
- kubernetes - 外部 ip 待定 Kubernetes 负载均衡器
- python - 如何在 python 元组中获取不同的元素?
- javascript - 如何将数据附加到嵌套数组元素
- asp.net-core - 如何将 .net 核心项目从 vscode 发布到 smarterasp.net?
- laravel - 如何在不使用循环的情况下从嵌套关系中检索数据
- openstack - 如果我有 UUID,我可以获得文件路径吗?
- javascript - 基于输入链接到站点的问题
- r - 重新排序与输入相同的组图
- c++ - 函数模板和模糊模板参数
- angular - 如何使用 Heroku 上托管的 Angular App 修复 CORS?