Spark Scala中数据帧的行内容的条件

Que*_*een 3 scala dataframe apache-spark apache-spark-sql

我有以下数据帧:

+--------+---------+------+
|  value1| value2  |value3|
+--------+---------+------+
|   a    |  2      |   3  |
+--------+---------+------+
|   b    |  5      |   4  |
+--------+---------+------+
|   b    |  5      |   4  |
+--------+---------+------+
|   c    |  3      |   4  |
+--------+---------+------+
Run Code Online (Sandbox Code Playgroud)

我想在value1 = b时输入行的value2/value3的结果,然后在名为"result"的新字段中为所有行 (甚至是不属于b 的行)添加它.这意味着必须将另一列添加到数据框中.例如,对于所有行,应该将5/4(我选择它,因为b)的结果添加到数据帧中.我知道,我应该使用这段代码:

 val dataframe_new = Dataframe.withColumn("result", $"value1" / $"value2")
 Dataframe.show()
Run Code Online (Sandbox Code Playgroud)

但是,我怎么能以这样的方式放置条件,它将它添加到所有行.输出应如下所示:

+---+---+---+------+
| v1| v2| v3|result|
+---+---+---+------+
|  a|  2|  3|  1.25|
|  b|  5|  4|  1.25|
|  b|  5|  4|  1.25|
|  c|  3|  4|  1.25|
+---+---+---+------+
Run Code Online (Sandbox Code Playgroud)

你能帮助我吗?提前致谢.

eli*_*sah 7

你只需要使用when:

scala> val df = Seq(("a",2,3),("b",5,4),("b",5,4),("c",3,4)).toDF("v1","v2","v3")
df: org.apache.spark.sql.DataFrame = [v1: string, v2: int ... 1 more field]

scala> df.withColumn("result", when($"v1" === "b" , ($"v2"/$"v3"))).show
+---+---+---+------+
| v1| v2| v3|result|
+---+---+---+------+
|  a|  2|  3|  null|
|  b|  5|  4|  1.25|
|  b|  5|  4|  1.25|
|  c|  3|  4|  null|
+---+---+---+------+
Run Code Online (Sandbox Code Playgroud)

你可以嵌入多个when如下:

scala> df.withColumn("result", when($"v1" === "b" , ($"v2"/$"v3")).
     |    otherwise(when($"v1" === "a", $"v3"/$"v2"))).show
+---+---+---+------+
| v1| v2| v3|result|
+---+---+---+------+
|  a|  2|  3|   1.5|
|  b|  5|  4|  1.25|
|  b|  5|  4|  1.25|
|  c|  3|  4|  null|
+---+---+---+------+
Run Code Online (Sandbox Code Playgroud)

编辑:似乎你需要其他条件,其中条件v1始终具有相同的值v2,v3并允许我们执行以下操作:

使用Spark 2+:

scala> val res = df.filter($"v1" === lit("b")).distinct.select($"v2"/$"v3").as[Double].head
res: Double = 1.25
Run Code Online (Sandbox Code Playgroud)

在Spark <2之前:

scala> val res = df.filter($"v1" === lit("b")).distinct.withColumn("result",$"v2"/$"v3").rdd.map(_.getAs[Double]("result")).collect()(0)
res: Double = 1.25                                                              

scala> df.withColumn("v4", lit(res)).show
+---+---+---+----+
| v1| v2| v3|  v4|
+---+---+---+----+
|  a|  2|  3|1.25|
|  b|  5|  4|1.25|
|  b|  5|  4|1.25|
|  c|  3|  4|1.25|
+---+---+---+----+
Run Code Online (Sandbox Code Playgroud)

  • @eliasah您可以使用`.as [Double] .head`而不是`.rdd.map().collect()` (2认同)