pyspark - 如何在 pyspark 中获得确定性随机排序?
问题描述
我想随机排序一个数据框,但是以一种确定的方式。我认为这样做的方法是使用orderBy
种子rand
函数。但是,我发现这在不同的机器上是不确定的。例如,考虑以下代码:
from pyspark.sql import types as T, functions as F
df = spark.createDataFrame(range(10), T.IntegerType())
df = df.orderBy(F.rand(seed=123))
print(df.show())
当我在本地机器上运行它时,它会打印
+-----+
|value|
+-----+
| 3|
| 4|
| 9|
| 7|
| 8|
| 0|
| 5|
| 6|
| 2|
| 1|
+-----+
但在 EC2 实例上,它会打印
+-----+
|value|
+-----+
| 9|
| 5|
| 6|
| 7|
| 0|
| 1|
| 4|
| 8|
| 3|
| 2|
+-----+
即使在不同的机器上运行,我如何才能获得确定性的随机排序?
我的 pyspark 版本是 2.4.1
编辑:顺便说一句,我应该补充一点,只是df.select(F.rand(seed=123)).show()
在两台机器上产生相同的输出,所以这特别是和组合的orderBy
问题rand
。
解决方案
感谢您从编辑中提供的额外信息!结果证明这是一个非常重要的线索。
问题
我认为这里的问题是您将伪随机生成的列附加到已经随机排序的数据集,并且现有的随机性不是确定性的,因此附加另一个确定性的随机源没有帮助。
您可以通过改写您的电话来验证这一点,orderBy
例如:
df.withColumn('order', F.rand(seed=123)).orderBy(F.col('order').asc())
如果我是对的,你会在两台机器上看到相同的随机值,但它们会附加到不同的行:随机值附加到行的顺序是随机的!
解决方案
如果这是真的,那么解决方案应该非常简单:在“真实”值上应用确定性、非随机排序,然后在顶部应用随机(但仍然是确定性)排序。
df.orderBy(F.col('value').asc()).withColumn('order', F.rand(seed=123)).orderBy(F.col('order').asc())
应该在两台机器上产生相似的输出。我的结果:
+-----+-------------------+
|value| order|
+-----+-------------------+
| 4|0.13617504799810343|
| 5|0.13778573503201175|
| 6|0.15367835411103337|
| 9|0.43774287147238644|
| 0| 0.5029534413816527|
| 1| 0.5230701153994686|
| 7| 0.572063607751534|
| 8| 0.7689696831405166|
| 3| 0.82540915099773|
| 2| 0.8535692890157796|
+-----+-------------------+
推荐阅读
- c# - Linq 查询以迭代组并仅过滤选定类型
- c - C中的二进制到十进制。我该如何改进它?
- python - 如何将字符串扩展为数据框中的多行?
- php - Discord Oauth2 PHP 中的 JPEG 头像
- typescript - Visual Studio Code:使用扩展以编程方式查找和替换特定文本
- android - 转换为 int 出错了。安卓
- python - (Python 3 ATM程序)每次提款和存款时如何更新余额?
- docusignapi - 提供访问令牌时,Docusign UserInfo 端点返回 401 Unauthorized
- javascript - node.js 可以让 Web 浏览器(客户端)访问我计算机中的任何目录吗?
- c# - 从数据库中检索自动增量数并基于此更新子行