基于列值在中添加增量id

axzmvihb  于 2021-05-27  发布在  Spark
关注(0)|答案(2)|浏览(341)

我想基于列值在中创建一个增量id。
例如,如果我有下表

-----------------------
| id |   value    |
-----------------------
| 3  |    a       |
| 2  |    a       | 
| 1  |    b       |
| 4  |    b       |
| 5  |    c       |
-----------------------

我想创建一个新列,其中包含一个随机或增量标识符,该标识符对于columen值是唯一的,如下所示:

-----------------------------------------------
| id |   value    |    new_id    |
-----------------------------------------------
| 3  |    a       |     1        | 
| 2  |    a       |     1        |
| 1  |    b       |     2        |
| 4  |    b       |     2        |
| 5  |    c       |     3        |
-----------------------------------------------

除了以后使用distinct和JOIN之外,还有别的选择吗?
谢谢!

v64noz0r

v64noz0r1#

一种直接的方法是获得列值的散列。这应该是一个无冲突散列,并将防止扫描整个数据集。
使用scala,

val sparkSession = ???
import sparkSession.implicits._
import org.apache.spark.sql.functions._

val df = ???
val dfModified = df.withColumn("new_id", hash(col("value")).cast("string"))

注意,如果有一组固定的已知值,那么应该创建 value -> id 预先Map并使用广播连接或udf放置新的id。如果您不使用scala,方法将是相同的,您只需要使用不同的散列技术。
希望这有帮助,干杯。

dxxyhpgq

dxxyhpgq2#

您可以在窗口中使用densed_rank()和order by value,但是这会将所有数据移动到单个分区,因此对于大型数据集的性能很差。

val window =   Window.orderBy($"value")

df.withColumn("new_id", dense_rank.over(window))

edit—使用虚拟分区似乎可以确保将数据洗牌到spark.sql.shuffle.partitions中

val window =   Window.partitionBy(lit(0)).orderBy($"value")

相关问题