我有一个火花数据框,例如
+-----+---+---+---+------+
|group| a| b| c|config|
+-----+---+---+---+------+
| a| 1| 2| 3| [a]|
| b| 2| 3| 4|[a, b]|
+-----+---+---+---+------+
val df = Seq(("a", 1, 2, 3, Seq("a")),("b", 2, 3,4, Seq("a", "b"))).toDF("group", "a", "b","c", "config")
如何添加其他列,即
df.withColumn("select_by_config", <<>>).show
是作为结构或JSON组合的列(由config
指定),类似于类似于名为struct / spark struct / json列的配置单元?注意,该结构是针对每个组的,对于整个数据帧而言并非恒定;在config
列中指定。
我可以想象df.map
可以解决问题,但是序列化开销似乎并不高效。如何通过仅SQL表达式实现此目的?也许是地图类型的列?
2.2可能但很笨拙的解决方案是:
val df = Seq((1,"a", 1, 2, 3, Seq("a")),(2, "b", 2, 3,4, Seq("a", "b"))).toDF("id", "group", "a", "b","c", "config")
df.show
import spark.implicits._
final case class Foo(id:Int, c1:Int, specific:Map[String, Int])
df.map(r => {
val config = r.getAs[Seq[String]]("config")
print(config)
val others = config.map(elem => (elem, r.getAs[Int](elem))).toMap
Foo(r.getAs[Int]("id"), r.getAs[Int]("c"), others)
}).show
有什么更好的方法可以解决2.2的问题?
答案 0 :(得分:1)
如果使用最新版本(Spark 2.4.0 RC 1或更高版本),则应使用较高阶函数的组合。创建列映射:
import org.apache.spark.sql.functions.{
array, col, expr, lit, map_from_arrays, map_from_entries
}
val cols = Seq("a", "b", "c")
val dfm = df.withColumn(
"cmap",
map_from_arrays(array(cols map lit: _*), array(cols map col: _*))
)
和transform
的{{1}}:
config