我有一个包含许多字段的数据集,字段“ valuefieldname”之一是引用/指针列,其中包含应处理的字段的field_name。如何基于“ valuefieldname”列动态获取该列值?
我需要类似于下面的代码(不起作用)
val dataSet2 = dataSet1.withColumn("targetoutput", col(col("valuefieldname")))
答案 0 :(得分:1)
尚无法在Spark计划中直接动态引用列。因此,动态访问必须通过作为计划一部分的数据结构或通过多个计划进行。这导致了解决问题的三种策略:
使用UDF动态寻址Row
中的字段。这是最通用,最简单的方法。当列数过多和/或数据稀疏时,此方法最有效。
构建一个MapType
列并对其进行引用。在某些情况下,这可能比(1)更为有效。
对数据进行多次(浅)传递并合并结果。最好在列数少且每列中的数据“重”(例如,结构化数据深且密集)时使用。
这是怎么做(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|
+--------+---------+