需要快速算法来从数万亿的关系记录中找到互斥的网络(关系)

时间:2017-07-07 09:04:06

标签: algorithm pyspark bigdata

我正在用一个带有两列(col1,col2)的假设表解释我的问题,如下所示:

col1   col2
A <--> B
A <--> C
E <--> F
B <--> D   
E <--> G

此表位于文件中。在上面的例子中,我想把它分成互斥的关系文件。因此,上表的结果将是两个文件(表):

col1   col2
A <--> B
A <--> C    
B <--> D   

col1   col2   
E <--> F     
E <--> G

真实文件有数万亿个独特的记录(关系),我想把它分成互斥的关系文件。需要任何智能算法的帮助。我正在使用pyspark从镶木地板文件中读取表格。所以,任何pyspark代码都会非常好但不是必需的(算法更重要)。

2 个答案:

答案 0 :(得分:1)

通过“互斥”,你可能意味着没有一个共同的节点。此问题称为图中连接组件的枚举。您可以使用Union-Find技术解决它。

对于每个节点,您将链接关联到属于同一组件的另一个节点。在考虑新关系时,让其中一个成员链接到另一个。

有关详细信息,请参阅https://en.wikipedia.org/wiki/Disjoint-set_data_structure。 这个过程很快,您可以通过所谓的路径压缩技术来加速它。

最后,每个组件都有一个没有链接到任何其他组件的节点,列出所有组件及其包含的节点并不是什么大事。

处理给定示例的步骤可以是

A -> B
C -> A -> B
C -> A -> B, E -> F
C -> A -> B -> D, E -> F
C -> A -> B -> D, E -> F -> G

(你获得线性列表的事实纯粹是偶然的)。

答案 1 :(得分:0)

使用Spark,速度非常快。对于那些处理大数据的人来说,这很有用:

from pyspark import SparkContext
from pyspark.sql.types import *
from pyspark.sql import Row
from pyspark.sql import SparkSession
from pyspark.sql.functions import col, size, length
from pyspark.sql.functions import *


spark = SparkSession.builder \
    .appName("Python Spark SQL") \
    .config("spark.driver.memory", "32g") \
    .config("spark.executor.memory", "32g") \
    .config("spark.executor.cores", "12") \
    .config("spark.local.dir", "~/mytmp") \
    .config("spark.jars.packages", "graphframes:graphframes:0.5.0-spark2.1-s_2.11") \
    .getOrCreate()
SparkContext.setSystemProperty('spark.executor.memory', '32g')
sc = spark.sparkContext

df = spark.read.parquet("my_table_file.parquet")
df.registerTempTable("mytable")
# df has two columns : col1 and col2. Similar to hypothetical table presented in my question

v = spark.sql("select col1 as id from mytable union select col2 as id from mytable ")
e = spark.sql("select col1 as src, col2 as dst from mytable")
sc.setCheckpointDir("~/cc_checkpoint")

from graphframes import *
g = GraphFrame(v, e)
connected = g.connectedComponents()
connected.registerTempTable("mytable_connected_components")
connected.select("component").distinct().count()