以键为新列重塑键值对的火花数据框

Posted

技术标签:

【中文标题】以键为新列重塑键值对的火花数据框【英文标题】:Reshape spark data frame of key-value pairs with keys as new columns 【发布时间】:2016-09-01 08:49:27 【问题描述】:

我是 spark 和 scala 的新手。假设我有一个作为键值对的列表数据框。有没有办法将列 id 的 id vars 映射为新列?

df.show()
+--------------------+--------------------  +
| ids                | vals                 |
+--------------------+--------------------  +
|[id1,id2,id3]       | null                 |
|[id2,id5,id6]       |[WrappedArray(0,2,4)] |
|[id2,id4,id7]       |[WrappedArray(6,8,10)]|

预期输出:

+----+----+
|id1 | id2| ...
+----+----+
|null| 0  | ...
|null| 6  | ...

【问题讨论】:

【参考方案1】:

一种可能的方法是计算新 DataFrame 的列并使用这些列来构造行。

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

val data = List((Seq("id1","id2","id3"),None),(Seq("id2","id4","id5"),Some(Seq(2,4,5))),(Seq("id3","id5","id6"),Some(Seq(3,5,6))))

val df = sparkContext.parallelize(data).toDF("ids","values")

val values = df.flatMap
  case Row(t1:Seq[String], t2:Seq[Int]) => Some((t1 zip t2).toMap)
  case Row(_, null) => None


// get the unique names of the columns across the original data
val ids = df.select(explode($"ids")).distinct.collect.map(_.getString(0))

// map the values to the new columns (to Some value or None)
val transposed = values.map(entry => Row.fromSeq(ids.map(id => entry.get(id))))

// programmatically recreate the target schema with the columns we found in the data
import org.apache.spark.sql.types._
val schema = StructType(ids.map(id => StructField(id, IntegerType, nullable=true)))

// Create the new DataFrame
val transposedDf = sqlContext.createDataFrame(transposed, schema)

此过程将通过数据 2 次,尽管取决于支持数据源,计算列名可能相当便宜。

此外,这在DataFramesRDD 之间来回切换。我有兴趣看到一个“纯”的 DataFrame 过程。

【讨论】:

谢谢!我设法简化了我的问题并以更简单的方式解决了它,而不需要通用解决方案(过滤数据为我呈现了一个在所有行上都具有相同 id 的 DF)。 最后我需要你的解决方案。但是,我知道,warning: non-variable type argument String in type pattern Seq[String] (the underlying of Seq[String]) is unchecked since it is eliminated by erasure 直接运行您的示例。 @johnblund 这是由于类型擦除导致的 JVM 限制。为了避免警告,必须在运行时将对象(上面的 t1、t2)转换为它们的类型。但是在这里声明类型,有助于编译器静态验证代码,我们知道它是正确的。

以上是关于以键为新列重塑键值对的火花数据框的主要内容,如果未能解决你的问题,请参考以下文章

字典,字典永远以键值对的方式出现,不会出现没有键或者没有值得情况

java问题,我想在java中存储键值对,以便使用,但是键值对的键和值都有重复元素,使用hashmap会产生覆盖。

列表的所有的input,将它的值以键值对的形式存放到一个数组里

对象键值对的形式 转换成对象组成数组的形式(键为值的形式)

对象键值对的形式 转换成对象组成数组的形式(键为值的形式)

python-字典