逐行比较具有相同模式的两个数据帧

时间:2017-12-06 17:06:01

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

我需要逐行比较spark数据框中的两个表(即数据帧),并获得特定列的较小值的每一行。例如:

enter image description here

假设我想让每个学生获得较低得分主题的每一行,所以我想要这个结果:

enter image description here

我正在考虑首先使用id作为连接属性加入数据框,但我的原始表格很大并且具有更多属性。看来如果没有加入,这是可行的。我能找到的最接近的问题是this,但我不知道如何将其应用到我的案例中。

带连接的顺便说一句解决方案也很明显,我只是在考虑是否有更好的解决方案。

1 个答案:

答案 0 :(得分:2)

如果没有连接,则无法执行此操作,除非您可以保证每个分区中的每个分区和记录都具有相同数量的分区和记录。然后你可以转换为RDD和zip。否则只需join

import org.apache.spark.sql.functions.{least, struct}

val df1 = Seq(
  (345, "math", 70), (992, "chem", 76), (223, "bio", 80)
).toDF("id", "subject", "score")

val df2 = Seq(
  (345, "psy", 64), (992, "ant", 94), (223, "math",   45)
).toDF("id", "subject", "score")

df1.alias("df1")
  .join(df2.alias("df2"), Seq("id"))
  .select($"id", 
    least(struct($"df1.score", $"df1.subject"),
          struct($"df2.score", $"df2.subject")).alias("score"))
  .select($"id", $"score.subject", $"score.score")

// +---+-------+-----+
// | id|subject|score|
// +---+-------+-----+
// |345|    psy|   64|
// |992|   chem|   76|
// |223|   math|   45|
// +---+-------+-----+

import org.apache.spark.sql.functions.when

df1.alias("df1")
  .join(df2.alias("df2"), Seq("id"))
  .select(
    $"id",
    when($"df1.score" < $"df2.score", $"df1.subject").otherwise($"df2.subject").alias("subject"),
     least($"df1.score", $"df2.score").alias("score"))

// +---+-------+-----+
// | id|subject|score|
// +---+-------+-----+
// |345|    psy|   64|
// |992|   chem|   76|
// |223|   math|   45|
// +---+-------+-----+