当前位置: 首页 > 知识库问答 >
问题:

Spark Dataframe:在structType值中表示具有非同构数据类型的MapType架构

盖昀
2023-03-14

我正在尝试创建一个传递给from_jsonAPI的structType模式,以便解析存储为JSON字符串的列。JSON数据包含一个Map,其中包含String键和struct类型的值,但每个struct的模式取决于键。

考虑这个JSON示例,其中“数据”列是一个具有值name地址的Map,并且每个值的架构都不同:

{
  "data": {
    "name": {
      "first": "john"
    },
    "address": {
      "street": "wall",
      "zip": 10000
    }
  }
}

对于键“名称”,结构值有一个成员字段“first”。对于键“地址”,结构值有两个成员字段“Street”和“zip”。

“数据”列可以在Spark数据框中表示为MapType[StringType, structType]吗?

  1. Spark是否处理结构非同构的Map[String, struct]?
  2. 如果是,请分享一个代表带有模式MapType的数据框的structType模式示例

编辑:要添加此类数据的另一个示例,该示例具有一个Map[String,Struct],其中该结构在整个Map值中不属于同一模式,请考虑以下情况:

case class Address(street: String, zip: Int)
case class Name(first: String)
case class Employee(id: String, role: String)
val map = Map(
  "address" -> Address("wall", 10000),
  "name" -> Name("john"),
  "occupation" -> Employee("12345", "Software Engineer")
)

如您所见,映射的值在其模式中有所不同——地址、名称和雇员都是不同的case类,它们的成员字段也不同。

您可以想象这种数据来自JSON文件,在该文件中,映射可以跨键具有任意类型的值,并且对所有相同类型的值没有限制。在我的例子中,我的值都是结构,但每个结构的模式依赖于映射键。


共有1个答案

孔彭祖
2023-03-14

您可以读取JSON列并动态解析模式:

scala prettyprint-override">import org.apache.spark.sql.functions.{col, from_json}
import spark.implicits._


val df = sc.parallelize(Seq(
  ("""{"data":{"name":{"first":"john"},"address":{"street":"wall","zip":10000},"occupation":{"id":"12345","role":"Software Engineer"}}}"""),
  ("""{"data":{"name":{"first":"john"},"address":{"street":"wall","zip":10000}}}"""),
)).toDF("my_json_column")

val rows = df.select("my_json_column").as[String]
val schema = spark.read.json(rows).schema

// Transforming your String to Struct
val newDF = df.withColumn("obj", from_json(col("my_json_column"), schema))

newDF.printSchema
// root
//  |-- my_json_column: string (nullable = true)
//  |-- obj: struct (nullable = true)
//  |    |-- data: struct (nullable = true)
//  |    |    |-- address: struct (nullable = true)
//  |    |    |    |-- street: string (nullable = true)
//  |    |    |    |-- zip: long (nullable = true)
//  |    |    |-- name: struct (nullable = true)
//  |    |    |    |-- first: string (nullable = true)
//  |    |    |-- occupation: struct (nullable = true)
//  |    |    |    |-- id: string (nullable = true)
//  |    |    |    |-- role: string (nullable = true)

newDF.select("obj.data", "obj.data.occupation.id").show(false)

输出

+---------------------------------------------------+-----+
|data                                               |id   |
+---------------------------------------------------+-----+
|{{wall, 10000}, {john}, {12345, Software Engineer}}|12345|
|{{wall, 10000}, {john}, null}                      |null |
+---------------------------------------------------+-----+
 类似资料:
  • 问题内容: 我想存储有关歌曲文件的信息,这些文件按以下类别分类: 1.流派,例如流行,摇滚,古典等 。2.使用乐器,例如钢琴小提琴等 。3.艺术家 每首歌曲都有许多乐器。每首歌都有很多歌手。 因此,所有关系都是多对多的。我该如何实施?在歌曲实体和这三个类别类型的实体之间建立多对多关系是个好主意吗?还是我应该只有一个继承那些子类别的类别实体? 提前致谢 问题答案: 乐器和艺术家都是“具有”关系的例子

  • 这实际上与我之前的问题相同,但使用Avro而不是JSON作为数据格式。 我正在使用一个Spark数据框架,它可以从几个不同的模式版本之一加载数据: 我正在使用Spark Avro加载数据。 它可能是版本一文件或版本二文件。但是我希望能够以相同的方式处理它,将未知值设置为“null”。我之前的问题中的建议是设置模式,但是我不想重复自己在文件中编写模式,也不想重复自己在和朋友中编写模式。如何将avro

  • 我有一个类似这样的JSON: 我正在尝试将此结构映射到 Spark 架构。我已经创建了以下内容;但是它不起作用。我还尝试在值字段映射中移除。 另外,请注意,它们“key1”和“key2”是动态字段,将使用唯一标识符生成。也可以有两个以上的键。有没有人能够将数组类型映射到结构类型?

  • 问题内容: 我有一张桌子,看起来像 而且我知道每个测试最多可以有3个,所以我想创建一个看起来像 我环顾四周,似乎需要使用PIVOT表。唯一的问题是,我找到了使用序数变量创建列的示例。在这种情况下,我具有预定义数量的可能列(3)。有任何想法吗? 问题答案: 不需要多个自联接的解决方案: 您可以根据分析函数的结果获取所需的输出: 输出 : 或者,仅使用聚合函数:

  • 我是新的spark和python,面临着从元数据文件构建模式的困难,该模式可以应用于我的数据文件。场景:数据文件的元数据文件(csv格式),包含列及其类型:例如: 我已成功将其转换为如下数据帧: 但是当我尝试用这个将其转换为StructField格式时 或 然后使用 我得到以下错误: 一旦我准备好了模式,我想使用createDataFrame来应用于我的数据文件。这个过程必须为许多表完成,所以我不

  • 1.2.2 非数值数据的表示 计算机除了具有进行数值计算能力之外,还具有进行非数值计算的能力。现在,后者的应用领域已远远超过了前者的应用领域,如:文字处理、图形图象处理、信息检索、日常的办公管理等。所以,对非数值信息的编码就显得越加重要。 1、ASCII码 ASCII码(American Standard Code for Information Interchange)是目前应用极其广泛的一种信