scala 如何根据分配的优先级选择最重要的行?

ozxc1zmp  于 2022-11-23  发布在  Scala
关注(0)|答案(2)|浏览(145)

我试图转换一个df,其中一个id是重复的,将其转换为一行id,并从优先级列表中获取值。

-----------
id | value
-----------
1     MV1
1     MV2
2     VPV
2    Others

优先级列表是:
1.“MV1”
1.“MV2”
1.“VPV”
1.“其他”
因此输出应为:

-----------
id | value
-----------
1     MV1
2     VPV

我试着创建一个列,并分配一个数值(mv 1-〉1 mv 2-〉2),然后用一个窗口函数对它进行排序,只取第一行,但我不认为这是一个很好的解决方案。
最佳的做法是什么?
我用scala作为语言。

mccptt67

mccptt671#

我使用的技巧是在输入数据集和优先级(已排序)之间使用join

val priorities = Seq(
  "MV1",
  "MV2",
  "VPV",
  "Others").zipWithIndex.toDF("name", "rank")

val ids = Seq(
  (1, "MV1"),
  (1, "MV2"),
  (2, "VPV"),
  (2, "Others")).toDF("id", "priority")

val mins = ids
  .join(priorities)
  .where($"priority" === $"name")
  .groupBy("id")
  .agg(min("rank") as "min")
val q = mins.join(priorities).where($"min" === $"rank").select("id", "name")

结果似乎与预期相符。

scala> q.show
+---+----+
| id|name|
+---+----+
|  1| MV1|
|  2| VPV|
+---+----+
a6b3iqyw

a6b3iqyw2#

我解决这个问题的方法是使用withColumnrow_numberwindow函数,结果很简单。工作方式和这里发布的另一个答案一样,但我想是一种更优化的方式。

val result = inputDF
    .withColumn("row_number", row_number.over(Window.partitionBy($"id").orderBy($"id")))
    .where($"row_number" === 1)
    .drop("row_number")

这样,您可以通过id设置优先级,然后使用orderBy子句选择每个优先级的第一个。
干净高效:)

相关问题