为具有复杂列(Array <Map <String,String >>的DataFrame添加新列

时间:2019-11-02 00:15:56

标签: scala apache-spark databricks

我正在使用以下模式从外部源加载数据框:

 |-- A: string (nullable = true)
 |-- B: timestamp (nullable = true)
 |-- C: long (nullable = true)
 |-- METADATA: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- M_1: integer (nullable = true)
 |    |    |-- M_2: string (nullable = true)
 |    |    |-- M_3: string (nullable = true)
 |    |    |-- M_4: string (nullable = true)
 |    |    |-- M_5: double (nullable = true)
 |    |    |-- M_6: string (nullable = true)
 |    |    |-- M_7: double (nullable = true)
 |    |    |-- M_8: boolean (nullable = true)
 |    |    |-- M_9: boolean (nullable = true)
 |-- E: string (nullable = true)

现在,我需要添加新列METADATA_PARSED,其列类型为 Array 和以下案例类:

案例类META_DATA_COL(M_1:字符串,M_2:字符串,M_3, M_10:String

基于示例,我在这里的方法是创建一个UDF并传入METADATA列。但是,由于它是复杂类型,因此在解析它时会遇到很多麻烦。

在UDF中,对于“新”变量M_10,我还需要对该方法进行一些字符串操作。因此,我需要访问元数据列中的每个元素。

解决此问题的最佳方法是什么?我试图将源数据帧(+ METADATA)转换为案例类;但这不起作用,因为它在进入UDF时被转换回了Spark WrappedArray类型。

1 个答案:

答案 0 :(得分:0)

您可以使用类似这样的东西。

import org.apache.spark.sql.functions._

val tempdf  = df.select(
  explode( col("METADATA")).as("flat") 
)

val processedDf = tempdf.select( col("flat.M_1"),col("flat.M_2"),col("flat.M_3"))

现在写一个udf


def processudf = udf((col1:Int,col2:String,col3:String) => /* do the processing*/)

这应该有所帮助,如果您可以提供有关处理的更多详细信息,我可以提供更多帮助。