如何使用 spark.sql 将表列传递给 rand 函数?
Posted
技术标签:
【中文标题】如何使用 spark.sql 将表列传递给 rand 函数?【英文标题】:How to pass table column to rand function using spark.sql? 【发布时间】:2021-12-31 09:44:05 【问题描述】:我有一张表,在 hive 元数据中有两列 A
和 B
。当A
和B
对的值与其他记录相同时,我必须生成相同的随机数。
示例:值对 2.0 & 3.0
或 1.0 & 5.0
在那些使用 HASH 函数的记录上我将得到 hash_code
。这个hash_code
我将传递给随机函数以获取每个匹配记录的特定值。我可以简单地将 seed=123
传递给 rand 函数,但我无法将表列传递给 rand
函数。
编辑 1:
具有相同种子的函数rand(123)
将产生identical results
。
将哈希传递给 rand:
spark.sql("select *,rand(hash(A,B)) from table1").show()
出现以下错误:
AnalysisException: Input argument to rand must be an integer, long, or null constant.
如何使用spark.sql
将hash_code
传递给rand
函数?
【问题讨论】:
您使用的是哪个版本的 spark? @AlexandreJuma spark 3.0 即使可以将列传递给rand
函数,表达式rand(hash(A,B))
也不会为相同的输入A
和B
给出相同的结果。这是一个非确定性函数。
rand
函数接受单个 Long
作为种子而不是列。
查看 Spark 代码,在 3.2.0 中 rand()
输入参数是严格的文字,因此没有来自列的可迭代输入。在您的版本中,您得到的错误似乎模棱两可,但它的行为似乎也相同。我不会使用rand(seed)
来生成确定性值,因为在没有一些低级功夫的情况下,实现(仍然)无法遵守种子随机数生成函数的通常确定性行为(即:将分区计数固定为 1 )。
【参考方案1】:
在我的 cmets 之后,使用 Spark 根本不可能(至少现在)您正在寻找的东西,主要有 2 个原因:
函数rand
只能接受常量参数
此外,它是一个非确定性函数,因此在您的数据框中调用 rand(hash(A,B))
不会对相同的输入 A
和 B
给出相同的结果:
import pyspark.sql.functions as F
# the function rand is called with same value 123, still give different results
spark.range(3).withColumn("rand", F.rand(123)).show()
#+---+-------------------+
#| id| rand|
#+---+-------------------+
#| 0|0.24244888714603952|
#| 1| 0.4745014193615499|
#| 2|0.03951602781768582|
#+---+-------------------+
也就是说,如果您的意图是从 A
和 B
的哈希结果中得到一个介于 [0, 1]
之间的值,那么您可以通过将哈希除以 10...0length_of_hash
来使用此技巧:
spark.sql("""
SELECT A,
B,
hash(A,B) / rpad('1', length(hash(A,B)) + 1, '0') AS Id
FROM table1
""").show()
#+---+---+------------+
#| A| B| Id|
#+---+---+------------+
#|2.0|3.0|0.1475353518|
#|1.0|5.0| 0.649463331|
#|2.0|3.0|0.1475353518|
#|1.0|5.0| 0.649463331|
#+---+---+------------+
【讨论】:
【参考方案2】:正如一些 cmets rand
accepts only one parameter 所指出的,种子应该是一个常数,而不是一个列(这是您从 hash(A, B)
获得的)。
如果您的目的是从 A
和 B
列中生成密钥,则不应调用任何随机函数。只需使用哈希值即可。
【讨论】:
我的目的是根据哈希码生成随机数。如果你仔细看 hash_code 是 long 或 big-int 数。我想要 [0,1) 之间的值以上是关于如何使用 spark.sql 将表列传递给 rand 函数?的主要内容,如果未能解决你的问题,请参考以下文章