使用Spark Dataframe Scala将多个不同的列转换为Map列

10

我有一个数据框,其中有列:user, address1, address2, address3, phone1, phone2等等。 我想将这个数据框转换为 - user, address, phone where address = Map("address1" -> address1.value, "address2" -> address2.value, "address3" -> address3.value)

我已经使用下面的方法将列转换为Map:

val mapData = List("address1", "address2", "address3")
df.map(_.getValuesMap[Any](mapData))

但我不确定如何将其添加到我的数据框(df)中。

我对 Spark 和 Scala 还很陌生,真的需要一些帮助。

1个回答

13

Spark >= 2.0

您可以跳过 udf,并使用 map(Python 中的 create_map)SQL 函数:

import org.apache.spark.sql.functions.map

df.select(
  map(mapData.map(c => lit(c) :: col(c) :: Nil).flatten: _*).alias("a_map")
)

Spark < 2.0

据我所知,没有直接的方法可以完成此操作。您可以使用以下 UDF:

import org.apache.spark.sql.functions.{udf, array, lit, col}

val df = sc.parallelize(Seq(
  (1L, "addr1", "addr2", "addr3")
)).toDF("user", "address1", "address2", "address3")

val asMap = udf((keys: Seq[String], values: Seq[String]) => 
  keys.zip(values).filter{
    case (k, null) => false
    case _ => true
  }.toMap)

val keys = array(mapData.map(lit): _*)
val values = array(mapData.map(col): _*)

val dfWithMap = df.withColumn("address", asMap(keys, values))

另一种不需要UDF的选择是使用结构体字段而不是映射:


val dfWithStruct = df.withColumn("address", struct(mapData.map(col): _*))

最大的优点是它可以轻松处理不同类型的值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接