Как я могу разбить массив структур на столбцы в Spark? - PullRequest
0 голосов
/ 05 апреля 2019

У меня есть столбец, содержащий массив телефонных номеров, представленных в виде структур, и мне нужно поместить их в три столбца с помощью атрибута "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

Этот ответ показывает, как поместить каждый элемент массива в отдельный столбец. Как разбить массив на несколько столбцов в 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 Ответ

1 голос
/ 05 апреля 2019

Вот один из способов, который включает в себя выравнивание номера телефона / факса через 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|
// +-------+-----------+-----------+-----------+
...