Python PySparks/Databricks中两列的图形处理

Python PySparks/Databricks中两列的图形处理,python,apache-spark-sql,databricks,Python,Apache Spark Sql,Databricks,假设我有以下两列的数据帧 value_1| value_2 ---------------- 1| 2 2| 3 4| 5 6| 5 4| 6 现在我想将我的所有值聚集到一个新的数据框中,其中列ID保存每个出现的值,列cluster\u ID表示以某种方式出现在一起的所有值的最小值: ID | cluster_ID ---------------- 1|

假设我有以下两列的数据帧

value_1| value_2
----------------
      1|       2
      2|       3
      4|       5
      6|       5
      4|       6
现在我想将我的所有值聚集到一个新的数据框中,其中列ID保存每个出现的值,列cluster\u 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没有保持集群列表的一个恒定状态

如何以更好的方式解决此问题

THX&BR
在我看来,这不像是聚类。如果您想使用Spark进行集群,您可以从下面的链接中找到一些关于从何处开始使用的想法


对我来说,这更像是一个图形问题,而不是聚类问题。在Databricks中,您可以通过将相关GraphFrames库上载到集群来使用GraphFrames。该算法计算出这些组。我使用了graphframes-0.8.0-spark3.0-s_2.12.jar,这取决于Spark(3.x)和Scala版本(2.12.x)

下面是一个简单的例子:

第1单元 细胞2 此时,
组件
数据帧将包含您需要的所有信息:

如果需要,您可以进一步操作它,例如将其保存到临时视图并在其上运行一些常规SQL:

第三单元 第4单元 SQL结果:


如果您的数据已经在数据框中,只需一个选择和一个where过滤器,就可以很容易地从原始数据框生成边缘数据框,例如,请参见此处以获得一个。

非常有效-非常感谢!你说得对,我把标题改成了graph processingWow。那看起来很酷。今天我学到了一些新东西。谢谢
%python
from graphframes import *

# Vertices dataframe
v = sqlContext.createDataFrame((
  ( 1, 2 ), ( 2, 3 ), ( 4, 5 ),
  ( 6, 5 ), ( 4, 6 )
)).toDF("id", "id2")

## Edge dataframe
e = sqlContext.createDataFrame((
  (1, 2, "is linked to"),
  (2, 3, "is linked to"),
  (4, 5, "is linked to"),
  (6, 5, "is linked to"),
  (4, 6, "is linked to") 
)).toDF("src", "dst", "relationship")


## Create the graph frame
g = GraphFrame(v, e)
print(g)
%python
## The connected components adds a component id to each 'group'
sc.setCheckpointDir("/tmp/graphframes-example-connected-components")

components = g.connectedComponents() ## doesn't work on Spark 1.4
display(components)
%python
components.createOrReplaceTempView("tmp")
%sql
SELECT id, component
FROM tmp
UNION
SELECT id2, component
FROM tmp
ORDER BY 1, 2