【发布时间】:2021-08-17 17:30:31
【问题描述】:
假设我有以下两列数据框
value_1| value_2
----------------
1| 2
2| 3
4| 5
6| 5
4| 6
现在我想将我的所有值聚集到一个新的数据帧中,其中列 ID 包含每个出现的值和列 cluster_ID 表示以某种方式一起出现的所有值的最小值:
ID | cluster_ID
----------------
1| 1
2| 1
3| 1
4| 4
5| 4
6| 4
请注意,即使值 1 和 3 现在有直接链接,它们仍然聚集在 (1, 2, 3) 集群中,因为它们与值 2 有一个连接。
由于我不知道如何以 Sparks 方式解决此问题,因此我尝试执行以下操作:
首先,我创建了一个包含所有 ID 对的列表:
[[1, 2], [2, 3], [4, 5], [6, 5], [4, 6]]
然后我创建了一个列表列表,其中每个子列表都用这个 for 循环表示集群:
id_pair_list = [[1, 2], [2, 3], [4, 5], [6, 5], [4, 6]]
duplicate_list = []
for e in id_pair_list:
if not duplicate_list:
duplicate_list = [e]
else:
try:
index = next(i for i, value in enumerate(duplicate_list) if e[0] in value)
updated_list = duplicate_list[index]
updated_list.append(e[1])
duplicate_list[index] = updated_list
except StopIteration:
pass
try:
index = next(i for i, value in enumerate(duplicate_list) if e[1] in value)
updated_list = duplicate_list[index]
updated_list.append(e[0])
duplicate_list[index] = updated_list
except StopIteration:
duplicate_list.append(e)
set_duplicate_list = []
for e in duplicate_list:
set_duplicate_list.append(sorted(list(set(e))))
根据需要,结果如下所示:
[[1, 2, 3], [4, 5, 6]]
在此之后,我创建了这样的新数据框:
id_mapping_df = spark.createDataFrame(
[[set_duplicate_list]],
['col']
).select(
F.explode('col').alias('ID')
).withColumn(
'cluster_id',
F.array_min('ID')
).withColumn(
'ID',
F.explode('ID')
)
这给了我最终的结果
...但是...
不幸的是,这只适用于我的小示例数据集。 当我用我更大的真实数据集尝试这个时,我突然遇到了问题,一些值出现在多个集群子列表中,不应该是这种情况。
我猜这已经发生了,因为带有 Sparks 的 for 循环是一种反模式,并且通过在我的 4 个节点上分配工作负载,Sparks 并没有保持我的集群列表的一个恒定状态。
如何以更好的 Sparks 兼容方式解决此问题?
THX & BR 进入数字
【问题讨论】:
标签: python apache-spark-sql databricks