如何在Spark中将结构数组拆分为列?

时间:2019-04-04 22:48:54

标签: json scala apache-spark schema

我有一列包含以结构表示的电话号码数组,需要通过“ type”属性(phone1, phone2, fax)将其分为三列。

这是该列的两个样本值。

[{"number":"000-000-0000","type":"Phone1"},{"number":"000-000-0001","type":"Phone2"},{"number":"000-000-0002","type":"Fax"}]
[{"number":"000-000-1000","type":"Phone1"},{"number":"000-000-1001","typeCode":"Fax"},{"number":"000-000-1002","type":"Phone2"}]

我想将它们分为三列,每种类型一列。 我想要这样的东西:

   Phone1           Phone2           Fax
000-000-0000     000-000-0001     000-000-0002
000-000-1000     000-000-1002     000-000-1001

此答案显示了如何将数组的每个元素放入其自己的列中。 How to explode an array into multiple columns in Spark

这使我半途而废,但是我不能依赖数组中项目的顺序。如果执行此操作,将会得到类似的内容,其中第二列中的Phone2和Fax值不正确。

   Phone1           Phone2           Fax
000-000-0000     000-000-0001     000-000-0002
000-000-1000     000-000-1001     000-000-1002

如何使用类型值将单列值分为三列?数组可以有0-3个数字,但每种类型最多只能有一个数字。

1 个答案:

答案 0 :(得分:1)

这是一种方法,其中涉及通过explode将电话/传真号码展平,然后在typeCode上旋转,如下例所示:

case class Contact(number: String, typeCode: String)

val df = Seq(
  (1, Seq(Contact("111-22-3333", "Phone1"), Contact("111-44-5555", "Phone2"), Contact("111-66-7070", "Fax"))),
  (2, Seq(Contact("222-33-4444", "Phone1"), Contact("222-55-6060", "Fax"), Contact("111-77-8888", "Phone2")))
).toDF("user_id", "contacts")

df.
  withColumn("contact", explode($"contacts")).
  groupBy($"user_id").pivot($"contact.typeCode").agg(first($"contact.number")).
  show(false)
// +-------+-----------+-----------+-----------+
// |user_id|Fax        |Phone1     |Phone2     |
// +-------+-----------+-----------+-----------+
// |1      |111-66-7070|111-22-3333|111-44-5555|
// |2      |222-55-6060|222-33-4444|111-77-8888|
// +-------+-----------+-----------+-----------+
相关问题