Spark:基于另一列的值动态引用一列

时间:2019-03-17 11:23:03

标签: apache-spark apache-spark-sql

我有一个包含许多字段的数据集,字段“ valuefieldname”之一是引用/指针列,其中包含应处理的字段的field_name。如何基于“ valuefieldname”列动态获取该列值?

我需要类似于下面的代码(不起作用)

val dataSet2 = dataSet1.withColumn("targetoutput", col(col("valuefieldname")))

1 个答案:

答案 0 :(得分:1)

尚无法在Spark计划中直接动态引用列。因此,动态访问必须通过作为计划一部分的数据结构或通过多个计划进行。这导致了解决问题的三种策略:

  1. 使用UDF动态寻址Row中的字段。这是最通用,最简单的方法。当列数过多和/或数据稀疏时,此方法最有效。

  2. 构建一个MapType列并对其进行引用。在某些情况下,这可能比(1)更为有效。

  3. 对数据进行多次(浅)传递并合并结果。最好在列数少且每列中的数据“重”(例如,结构化数据深且密集)时使用。

这是怎么做(1):

def getColumnAs[A](colName: String, row: Row): Option[A] = 
  if (row == null) None
  else {
    val idx = row.fieldIndex(colName)
    if (row.isNullAt(idx)) None else Some(row.getAs[A](idx))
  }

case class Data(col_name: String, x: Option[Int], y: Option[Int])

val df = spark.createDataset(Seq(
  Data("x", Some(1), None), 
  Data("x", Some(2), Some(20)), 
  Data("y", None,    Some(30))
)).toDF

val colValue = udf(getColumnAs[Int] _)

df.select(
    'col_name, 
    colValue('col_name, struct('*)).as("col_value")
  )
  .show

输出为

+--------+---------+
|col_name|col_value|
+--------+---------+
|       x|        1|
|       x|        2|
|       y|       30|
+--------+---------+