Как я могу взорвать структуру в кадре данных без жесткого кодирования имен столбцов?

Рассмотрим один из моих наборов данных в качестве примера ниже. Это результат df.printSchema()

member: struct (nullable = true)
 |   address: struct (nullable = true)
 |    |   city: string (nullable = true)
 |    |   state: string (nullable = true)
 |    |   streetAddress: string (nullable = true)
 |    |   zipCode: string (nullable = true)
 |   birthDate: string (nullable = true)
 |   groupIdentification: string (nullable = true)
 |   memberCode: string (nullable = true)
 |   patientName: struct (nullable = true)
 |    |   first: string (nullable = true)
 |    |   last: string (nullable = true)
memberContractCode: string (nullable = true)
memberContractType: string (nullable = true)
memberProductCode: string (nullable = true)

Эти данные считываются через json, и я хочу сгладить это, чтобы все находились на одном уровне и чтобы мой фрейм данных содержал только примитивные типы, например:

member.address.city: string (nullable = true)
member.address.state: string (nullable = true)
member.address.streetAddress: string (nullable = true)
member.address.zipCode: string (nullable = true)
member.birthDate: string (nullable = true)
member.groupIdentification: string (nullable = true)
member.memberCode: string (nullable = true)...

Я знаю, что это можно сделать, указав имена столбцов вручную:

df = df.withColumn("member.address.city", df("member.address.city")).withColumn("member.address.state", df("member.address.state"))...

Однако я не смогу жестко закодировать имена столбцов, как указано выше, для всех моих наборов данных, поскольку программа должна иметь возможность обрабатывать новые наборы данных на лету без каких-либо изменений в реальном коде. Я хочу сделать общий метод, который может взорвать любой тип структуры, учитывая, что он уже находится в кадре данных и схема известна (но является подмножеством полной схемы). Возможно ли это в Spark 1.6? И если да, то как

1 ответ

Решение

Это должно сделать это - вам нужно будет перебрать схему и "сплющить" ее, обрабатывая поля типа StructType отдельно от "простых" полей:

// helper recursive method to "flatten" the schema:
def getFields(parent: String, schema: StructType): Seq[String] = schema.fields.flatMap {
  case StructField(name, t: StructType, _, _) => getFields(parent + name + ".", t)
  case StructField(name, _, _, _) => Seq(s"$parent$name")
}

// apply to our DF's schema:
val fields: Seq[String] = getFields("", df.schema)

// select these fields:
val result = df.select(fields.map(name => $"$name" as name): _*)
Другие вопросы по тегам