【问题标题】:How to assign a unique ID to each corresponding unique column value?如何为每个对应的唯一列值分配唯一 ID?
【发布时间】:2020-06-19 11:52:17
【问题描述】:

想象一个如下图所示的数据框:

+-------+--------+---------+---------+--------+-----------------+---+
|address|lastname|firstname|patientid|policyno|visitid          |id |
+-------+--------+---------+---------+--------+-----------------+---+
|addr1  |Pits    |Rodney   |patid1   |policy1 |visituid_rodney_1| 1 |
|addr1  |Pits    |Rodney   |patid1   |policy1 |visituid_rodney_2| 1 |
|addr1  |Pits    |Rodney   |patid1   |policy1 |visituid_rodney_3| 1 |
|addr2  |Dobs    |Aliya    |patid2   |policy2 |visituid_aliya_1 | 2 |
|addr2  |Dobs    |Aliya    |patid2   |policy2 |visituid_aliya_2 | 2 |
|addr2  |Dobs    |OP       |patid3   |policy3 |visituid_OP_1    | 3 |
+-------+--------+---------+---------+--------+-----------------+---+

当名称 (firstname + lastname) 相同时,“id”的列值保持不变,当名称变得不同时 - 我想分配一个新的 id。

我需要这个,因为我想识别某个数据集(其中包含敏感细节),以便我可以在我的应用程序中使用相同的数据,但值已更改。字段id 将用作与其他数据帧连接的索引键。

关于id 的另一部分是其他虚拟数据帧也将包含类似的id 列,该列可能会使用monotonically_increasing_id() 填充,因此最好让id 从0 开始OR 1,以不断增加的方式。

如何在 scala 中实现这一目标?

【问题讨论】:

  • 您可以创建一个接受两列(姓氏、名字)并计算唯一 ID(例如通过哈希)的 UDF。
  • 嗨 @Blobonat 感谢 UDF 的想法。虽然我没有在我的帖子中提到它,但它确实在我脑海中浮现。如果有一些标准功能可以做这样的事情——那就太好了。如果不是 - 我想 UDF 将是要走的路。
  • 我已经更新了下面的解决方案,如果有帮助,请检查并接受或支持.. :)

标签: scala dataframe apache-spark uniqueidentifier


【解决方案1】:

使用window 函数。

scala> df.show(false)
+-------+--------+---------+---------+--------+-----------------+
|address|lastname|firstname|patientid|policyno|visitid          |
+-------+--------+---------+---------+--------+-----------------+
|addr1  |Pits    |Rodney   |patid1   |policy1 |visituid_rodney_1|
|addr1  |Pits    |Rodney   |patid1   |policy1 |visituid_rodney_2|
|addr1  |Pits    |Rodney   |patid1   |policy1 |visituid_rodney_3|
|addr2  |Dobs    |Aliya    |patid2   |policy2 |visituid_aliya_1 |
|addr2  |Dobs    |Aliya    |patid2   |policy2 |visituid_aliya_2 |
|addr2  |Dobs    |OP       |patid3   |policy3 |visituid_OP_1    |
|addr4  |AN      |OTHER    |patid4   |policy4 |visituid_OP_1    |
|addr2  |ANO     |THER     |patid5   |policy5 |visituid_OP_1    |
+-------+--------+---------+---------+--------+-----------------+
val expr = Seq("lastname","firstname")
            .map(c => hash(col(c)).as(c))
            .reduce(concat(_,_).asc)
val winSpec = dense_rank()
                .over(Window.orderBy(expr))

输出

scala> df.withColumn("id",winSpec).show(false)

+-------+--------+---------+---------+--------+-----------------+---+
|address|lastname|firstname|patientid|policyno|visitid          |id |
+-------+--------+---------+---------+--------+-----------------+---+
|addr1  |Pits    |Rodney   |patid1   |policy1 |visituid_rodney_1|1  |
|addr1  |Pits    |Rodney   |patid1   |policy1 |visituid_rodney_2|1  |
|addr1  |Pits    |Rodney   |patid1   |policy1 |visituid_rodney_3|1  |
|addr4  |AN      |OTHER    |patid4   |policy4 |visituid_OP_1    |2  |
|addr2  |Dobs    |OP       |patid3   |policy3 |visituid_OP_1    |3  |
|addr2  |Dobs    |Aliya    |patid2   |policy2 |visituid_aliya_1 |4  |
|addr2  |Dobs    |Aliya    |patid2   |policy2 |visituid_aliya_2 |4  |
|addr2  |ANO     |THER     |patid5   |policy5 |visituid_OP_1    |5  |
+-------+--------+---------+---------+--------+-----------------+---+

【讨论】:

  • 我很想知道其他人是否会看到这个。它令人费解,而不是使用dense_rank。另请查看 AN OTHER 与 ANO THER 名称。
  • @thebluephantom - 你关于 AN OTHER 与 ANO THER 的观点是正确的。同意这一点。
  • @thebluephantom,谢谢.. 现在我已经解决了这个问题。
  • 嗨@Srinivas:我接受了这个作为我的答案,因为它从 1 创建 id (尽管在我的情况下首选 0)。感谢您的时间、知识和努力。我真的很感激。
【解决方案2】:
import org.apache.spark.sql.functions._
val df = sc.parallelize(Seq(
  ("Xxx", "yyy"),
  ("xxx", "yyy"),
  ("aaa", "yyy")
)).toDF("c1", "c2")

df.withColumn("hashName", hash(concat($"c1", $"c2")))//.show(false)

那么有哪些明显的改进?哈希之前的大写或小写之间的分隔符。 如果不清理,用分隔符替换所有空格和奇数字符。

更好的是:

df.withColumn("preHashName", lower(trim(concat($"c1", lit("|"), $"c2"))))
  .withColumn("hashName", hash(lower(concat($"c1", lit("|"), $"c2")))).show(false)

不这样做意味着在另一个答案中,AN OTHER 在散列方面可能与 ANO THER 相同。

输出:

+---+------+-----------+-----------+
|c1 |c2    |preHashName|hashName   |
+---+------+-----------+-----------+
|Xxx|y yy  |xxx|y yy   |907198499  |
|xxx|yyy   |xxx|yyy    |-1167597858|
|aaa|yyy   |aaa|yyy    |495090835  |
+---+------+-----------+-----------+

【讨论】:

  • 您好,感谢您尝试提供解决方案。这很有趣。我从你的帖子和 cmets 中学到了很多东西。但这并没有帮助我在编辑后解决我的问题 - 我清楚地提到我需要将我准备好的 df(带有新 ID)与更多的 DF 加入,这些 DF 的 ID 从 0 开始 - 所以在这种情况下我不会能够使用填充的 ID 加入他们。再次感谢您的时间和精力。我真的很感激。
猜你喜欢
  • 2017-12-18
  • 1970-01-01
  • 1970-01-01
  • 2019-03-17
  • 2021-06-12
  • 2017-07-10
  • 2019-01-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多