当前位置: 首页 > 知识库问答 >
问题:

Spark/scala-我们可以从数据帧中的现有列值创建新列吗

伯英武
2023-03-14

我正在尝试查看我们是否可以使用 spark/scala 从 dataFrame 中某个列中的值创建新列。我有一个数据帧,其中包含以下数据

df.show()

+---+-----------------------+
|id |allvals                |
+---+-----------------------+
|1  |col1,val11|col3,val31  |
|3  |col3,val33|col1,val13  |
|2  |col2,val22             |
+---+-----------------------+

在上面的数据中,col1/col2/col3是列名,后跟它的值。列名和值由< code >,分隔。每组由< code>|分隔。

现在,我想做到这一点

+---+----------------------+------+------+------+
|id |allvals               |col1  |col2  |col3  |
+---+----------------------+------+------+------+
|1  |col1,val11|col3,val31 |val11 |null  |val31 |
|3  |col3,val33|col1,val13 |val13 |null  |val13 |
|2  |col2,val22            |null  |val22 |null  |
+---+----------------------+------+------+------+

感谢任何帮助。

共有2个答案

宦博超
2023-03-14

您可以使用自定义项将列转换为映射

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

val df = Seq(
  (1, "col1,val11|col3,val31"), (2, "col3,val33|col3,val13"), (2, "col2,val22")
).toDF("id", "allvals")

val to_map = udf((s: String) => s.split('|').collect { _.split(",") match {
  case Array(k, v) => (k, v)
}}.toMap )

val dfWithMap = df.withColumn("allvalsmap", to_map($"allvals"))
val keys = dfWithMap.select($"allvalsmap").as[Map[String, String]].flatMap(_.keys.toSeq).distinct.collect

keys.foldLeft(dfWithMap)((df, k) => df.withColumn(k, $"allvalsmap".getItem(k))).drop("allvalsmap").show
// +---+--------------------+-----+-----+-----+
// | id|             allvals| col3| col1| col2|
// +---+--------------------+-----+-----+-----+
// |  1|col1,val11|col3,v...|val31|val11| null|
// |  2|col3,val33|col3,v...|val13| null| null|
// |  2|          col2,val22| null| null|val22|
// +---+--------------------+-----+-----+-----+

受 user6910411 的这个答案的启发。

尉迟招
2023-03-14

您可以使用< code>split 、< code>explode和< code>groupBy/pivot/agg转换数据帧,如下所示:

val df = Seq(
  (1, "col1,val11|col3,val31"),
  (2, "col3,val33|col1,val13"),
  (3, "col2,val22")
).toDF("id", "allvals")

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

df.withColumn("temp", split($"allvals", "\\|")).
  withColumn("temp", explode($"temp")).
  withColumn("temp", split($"temp", ",")).
  select($"id", $"allvals", $"temp".getItem(0).as("k"), $"temp".getItem(1).as("v")).
  groupBy($"id", $"allvals").pivot("k").agg(first($"v"))

// +---+---------------------+-----+-----+-----+
// |id |allvals              |col1 |col2 |col3 |
// +---+---------------------+-----+-----+-----+
// |1  |col1,val11|col3,val31|val11|null |val31|
// |3  |col2,val22           |null |val22|null |
// |2  |col3,val33|col1,val13|val13|null |val33|
// +---+---------------------+-----+-----+-----+
 类似资料:
  • 假设,我有以下数据帧: 与 col1 不同的值(p1、p2、p3)单独具有 id,将用作最终数据帧的列。在这里,id y 对于相同的 col1 值 p2 有两个 col2 值(b2 和 b3),因此,p2 将被视为数组类型列。因此,最终的数据帧将是 如何从第一个数据帧高效地实现第二个数据帧?

  • 我有一个数据框,我正在使用TIA来填充彭博社的数据。当我看着df。索引我看到我打算成为列的数据以多索引的形式呈现给我。df的输出。列是这样的: 索引([u'column1','u'column2']) 我尝试过各种reset_index的迭代,但都无法补救这种情况。 1) TIA管理器如何使数据帧列作为索引读入? 2) 如何正确地将这些列标识为列而不是多索引? 我试图解决的最终问题是,当我尝试将此

  • 我有一个包含大量列的Spark数据框架。我想从中删除两列以获得新的数据帧。 如果列更少,我可以在API中使用select方法,如下所示: 但是既然从长列表中挑选列是一项乏味的任务,有解决方法吗?

  • 在Apache Spark 2.1.0中,我有两个数据帧aaa_01和aaa_ 02。 我对这两个数据帧执行内部联接,从两个数据帧中选择几个列以显示在输出中。 Join 工作正常,但输出数据帧具有与输入数据帧中存在的列名称相同的列名。我被困在这里。我需要使用新的列名称,而不是在输出数据帧中获取相同的列名称。 下面给出了示例代码供参考 我获取的输出数据帧的列名称为“col1,col2,col3”。我

  • 我有两个熊猫数据框 步骤2:对于flag=1的行,AA_new将计算为var1(来自df2)*组“A”和val“AA”的df1的'cal1'值*组“A”和val“AA”的df1的'cal2'值,类似地,AB_new将计算为var1(来自df2)*组“A”和val“AB”的df1的'cal1'值*组“A”和val“AB”的df1的'cal2'值 我的预期输出如下所示: 以下基于其他stackflow

  • 我得到以下错误:org.apache.spark.sql.analysisException:不允许在另一个聚合函数的参数中使用聚合函数。请在子查询中使用内部聚合函数。;; 我尝试了多种解决方案来解决这个问题,但似乎没有任何效果。所有的想法都得到了赞赏。谢了!