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

如何从结构类型的数组创建结构?

法烨烨
2023-03-14

如何合并数组中的所有结构并生成合并的结构?

例如,使用SparkSQL,我能够读取源json文件并生成数组类型的列,数组中的每个元素都包含一个键:值对。例如,假设我们有一个ArrayType列的值,该列的名称为coll,值为:[{a: 1},{b: 2},{c: 3}]

我需要将这个数组类型的列转换为结构类型,其值为{a:1,b:2,c:3}。

由于我是通过读取JSON文件获得模式的,所以我可以使用派生序号获得结果,如:

df.select(
  $"col.a".getItem(1) as "a", 
  $"col.b".getItem(2) as "b", 
  $"col.c".getItem(3) as "c")

这个解决方案的问题是,如果数组中的元素顺序不同,我会得到错误的结果。有没有一种干净的方法来合并所有键/值结构并干净地生成一个结构?在我的例子中,键没有重复,所以我不担心在覆盖键/值时丢失数据。

共有1个答案

邢璞
2023-03-14

如果我理解正确,可以使用分解和透视的组合:

scala> :paste
// Entering paste mode (ctrl-D to finish)

val df = Seq(
  (1, Array(("a", 1), ("b", 2), ("c", 3))),
  (2, Array(("b", 5), ("c", 6), ("a", 4)))
).toDF("id", "col")

df.show(10, false)

val explodedDF = df.withColumn("col2", explode(df.col("col"))).select("id", "col2")

explodedDF.show(10, false)

val flattenedDF = explodedDF.withColumn("k", $"col2._1").withColumn("v", $"col2._2").select("id", "k", "v")

flattenedDF.show(10, false)

val pivotedDF = flattenedDF.groupBy("id").pivot("k").agg(first(col("v")))

pivotedDF.show(10, false)

import scala.util.parsing.json.JSONObject

pivotedDF.select("a", "b", "c").collect().map{row => JSONObject(row.getValuesMap(row.schema.fieldNames))}.map(println)

// Exiting paste mode, now interpreting.

+---+------------------------+
|id |col                     |
+---+------------------------+
|1  |[[a, 1], [b, 2], [c, 3]]|
|2  |[[b, 5], [c, 6], [a, 4]]|
+---+------------------------+

+---+------+
|id |col2  |
+---+------+
|1  |[a, 1]|
|1  |[b, 2]|
|1  |[c, 3]|
|2  |[b, 5]|
|2  |[c, 6]|
|2  |[a, 4]|
+---+------+

+---+---+---+
|id |k  |v  |
+---+---+---+
|1  |a  |1  |
|1  |b  |2  |
|1  |c  |3  |
|2  |b  |5  |
|2  |c  |6  |
|2  |a  |4  |
+---+---+---+

+---+---+---+---+
|id |a  |b  |c  |
+---+---+---+---+
|1  |1  |2  |3  |
|2  |4  |5  |6  |
+---+---+---+---+

{"a" : 1, "b" : 2, "c" : 3}
{"a" : 4, "b" : 5, "c" : 6}
df: org.apache.spark.sql.DataFrame = [id: int, col: array<struct<_1:string,_2:int>>]
explodedDF: org.apache.spark.sql.DataFrame = [id: int, col2: struct<_1: string, _2: int>]
flattenedDF: org.apache.spark.sql.DataFrame = [id: int, k: string ... 1 more field]
pivotedDF: org.apache.spark.sql.DataFrame = [id: int, a: int ... 2 more fields]
import scala.util.parsing.json.JSONObject
res24: Array[Unit] = Array((), ())

scala> 
 类似资料:
  • 问题内容: 我是Java的新手,我试图找到一种方法来在C语言中存储诸如结构之类的信息。例如,说我想让一名程序雇用员工。它将从用户那里获得一个名字,姓氏和ID号并将其存储起来。然后,用户可以根据条件查看该信息(例如,如果数据库有多于1名员工)。有没有人建议这样做的最佳方法? 问题答案: C中的结构就像Java中的类一样,功能更强大,因为Java中的类可以包含方法,而C ++可以。您创建一个新类。例如

  • 问题内容: 我想我需要反射包才能做到这一点。说我有一个像这样的结构: 说我想生成ResolutionValue结构的JSON表示…是否有某种方法可以创建不实例化的JSON表示? 问题答案: 即使使用反射,也需要使用实际值来获取类型。因此,我建议您只使用类型的零值。

  • 问题内容: 如何创建泛型类型的数组?通用方法如何工作?它返回通用数组的副本。因此可以创建通用数组。但是如何?怎么能写一个类似的方法呢? 问题答案: 如果需要在运行时创建它,则至少需要在此时知道类型,因此可以使用以下方法: where 是泛型类型,是的类,并且是初始大小。 这里的文件

  • 我已经在Spark中读取了一个JSON文件。该文件具有以下结构: 我创建了一个递归函数来使用嵌套结构类型的列来展平架构 如何展平包含嵌套结构类型的ArrayType,例如engagementItems:数组(nullable=true) 感谢您的帮助。

  • 问题内容: C部分: 开始部分: 我可以通过这种方式获取数组的第一个元素。但是如何获得带有n个元素的整个数组呢?以及如何安全地释放它们? 问题答案: 首先,即使您正在使用Go,添加cgo时也不再存在任何“安全”。由您决定何时以及如何释放内存,就像使用C进行编程一样。 在go中使用C数组的最简单方法是通过数组将其转换为切片: 最大大小的数组实际上并未分配,但是Go需要恒定大小的数组,并且要足够大。该

  • 这可能是一个非常奇怪的问题,但我甚至不知道如何命名这个问题。我对C#和Selenium很陌生。我已经对它做了一些编码,我很乐意创建一个(quitemessy)测试,它可以按照我想要的方式运行。我想把我的考试安排得更好一点。 我将用这个例子来说明我想要实现的目标: 在登录页面上,我们可以说我有一个“登录”按钮,该按钮打开一个页面,让我输入我的凭证“用户名”和“密码”。 让我们说我想这样编程:有登录的