【问题标题】:Column Header Unpivot in a DataFrame (Spark Scala)数据帧中的列标题反透视(Spark Scala)
【发布时间】:2021-06-08 22:04:28
【问题描述】:

我正在寻找一种有效的方法来获取几列的标题,并将它们反透视到一个列中。这是一个例子:

我从一个看起来像这样的表开始。三列,每列一个标题。

| Header 1| Header 2| Header 3 |
___________________________________ 
| null    | null    | null    |
| null    | null    | null    |
| null    | null    | null    |

我想做的是这个->

| Some Name   | Unique Name | Unique Name | Unique Name
_______________________________________________________
| Header 1    | null        | null        | null
| Header 2    | null        | null        | null
| Header 3    | null        | null        | null

我实际上是在尝试将每列中的标题名称转置为单个列中它们自己的值,这将接收一个新的标题名称。行中的每个值也将成为新列的一部分,该列将接收新的标题名称。我了解如何获取一列并使用 .pivot() 函数根据列的值创建新标题,但我在反向操作时遇到了麻烦。

我的研究表明,Python 有 .melt(),这可能是也可能不是解决这个问题的理想方案,但作为一个新的 Scala 开发人员并第一次使用 Spark - 我可以使用一些建议来了解如何最好地解决问题这个。如果这比我想象的更简单,我深表歉意!

感谢您的所有帮助。

【问题讨论】:

  • 您想通过这种“旋转”实现什么目标?如果我理解正确,您不想执行任何聚合,您只想“翻转”表格?这里的这个问题与您所描述的类似:看看this 这似乎与您想要实现的目标相似。

标签: scala dataframe apache-spark apache-spark-sql


【解决方案1】:

看看 Scala 中的这种方法:

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

  def melt(
    df: DataFrame,
    idVars: Array[String],
    valueVars: Array[String],
    varName: String = "variable",
    valueName: String = "value"): DataFrame = {

    val columns = valueVars.map(c => Array(lit(c), col(c))).flatten
    val varsAndVals = map(columns: _*)
    df.select(idVars.map(col(_)).:+(explode(varsAndVals)): _*)
      .withColumnRenamed("key", varName)
      .withColumnRenamed("value", valueName)
  }

  def main(args: Array[String]): Unit = {
    val spark = SparkSession.builder().master("local[1]").getOrCreate()

    val df = spark
      .createDataFrame(
        spark.sparkContext.parallelize(
          Seq(Row("a", 1, 2, null), Row("b", 3, 4, 7), Row("c", 5, 6, 9))),
            StructType(
              List(
                StructField("A", StringType),
                StructField("B", IntegerType),
                StructField("C", IntegerType),
                StructField("D", IntegerType))))

    melt(df, Array("A"), Array("B", "C", "D")).show()
  }

输入数据框:

+---+---+---+----+
|  A|  B|  C|   D|
+---+---+---+----+
|  a|  1|  2|null|
|  b|  3|  4|   7|
|  c|  5|  6|   9|
+---+---+---+----+

未透视的 DF:

+---+--------+-----+
|  A|variable|value|
+---+--------+-----+
|  a|       B|    1|
|  a|       C|    2|
|  a|       D| null|
|  b|       B|    3|
|  b|       C|    4|
|  b|       D|    7|
|  c|       B|    5|
|  c|       C|    6|
|  c|       D|    9|
+---+--------+-----+

改编自这个问题How to melt Spark DataFrame?

【讨论】:

  • 这就是我要找的。感谢您花时间展示 Scala 中的 melt 实现示例。对我很有帮助。将您的答案标记为解决方案。
猜你喜欢
  • 1970-01-01
  • 2017-11-15
  • 2021-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-14
  • 1970-01-01
相关资源
最近更新 更多