Apache Spark根据列的不同值计算列值

时间:2020-05-08 11:39:37

标签: scala apache-spark

我正在处理以下表格,我想根据其他2列的不同值来计算新列(结果)。

| id1  | id2 | outcome
|  1   |  1  |  1
|  1   |  1  |  1
|  1   |  3  |  2
|  2   |  5  |  1 
|  3   |  1  |  1  
|  3   |  2  |  2
|  3   |  3  |  3

基于id1id2的组合值,结果应从1开始以递增顺序开始。任何提示都可以在Scala中完成。在这种情况下,row_number似乎没有用。

这里的逻辑是,对于id1的每个唯一值,我们将开始使用min({id2)对结果进行编号,而对应的id1被分配为1。

2 个答案:

答案 0 :(得分:1)

您可以尝试density_rank()

以您的示例

      val df = sqlContext
        .read
        .option("sep","|")
        .option("header", true)
        .option("inferSchema",true)
        .csv("/home/cloudera/files/tests/ids.csv") // Here we read the .csv files
        .cache()

      df.show()
      df.printSchema()

      df.createOrReplaceTempView("table")
      sqlContext.sql(
        """
          |SELECT id1, id2, DENSE_RANK() OVER(PARTITION BY id1 ORDER BY id2) AS outcome
          |FROM table
          |""".stripMargin).show()

输出

+---+---+-------+
|id1|id2|outcome|
+---+---+-------+
|  2|  5|      1|
|  1|  1|      1|
|  1|  1|      1|
|  1|  3|      2|
|  3|  1|      1|
|  3|  2|      2|
|  3|  3|      3|
+---+---+-------+

答案 1 :(得分:1)

使用Window函数将partition合并(first id),然后根据orderpartition合并成second id

现在,您只需要在每个dense_rank分区上分配一个等级(Window)。

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

df
.withColumn("outcome", dense_rank().over(Window.partitionBy("id1").orderBy("id2")))