从一个巨大的邻接列表中提取边列表的最有效方法是什么?

时间:2016-11-15 16:37:58

标签: python csv graph

这可能是一个愚蠢的问题,但是假设我有一个大的(〜十亿行)CSV文件,其中包含邻接列表,其中顶点由字符串表示,如:

+------------+---------------------------+
|     id     |         neighbors         |
+------------+---------------------------+
| 'james'    | 'michael, jane, pete'     |
| 'doug'     | 'cliff'                   |
| 'amy'      | 'bobby, russell, richard' |
| 'richard'  | 'kam, earl, cliff'        |
| 'marshawn' |                           |
| 'bobby'    | 'emily, james, doug'      |
+------------+---------------------------+

从这些类型的邻接列表中,我想要做的就是输出一个顶点集和一个由无向顶点对组成的边集。就是这样。

实现这一目标的最有效策略是什么?我们如何在Python中实现它?

为简洁起见下面的算法,请:

  • add('bobby'):将顶点'bobby'添加到顶点集
  • 的操作
  • edge('bobby','emily'):添加('bobby','emily')到边集的操作
  • ingraph('bobby'):检查顶点'bobby'是否在顶点集

假设我们采用从空图开始并按顺序添加顶点的方法。然后我的第一次尝试(非常原始的伪代码)将是这样的:

ids = [...all id's in the CSV...]
unexplored = list(ids)

for i in ids:
    add(i)
    for j in unexplored:
        if i in neighbors(j):
            if not ingraph(j): add(j)
            edge(i, j)              
    del unexplored[0]
  1. 是否有一种明显的方法可以改进这种算法(独立于Python)?
  2. 在Python中实现这样的解决方案的最佳方法是什么?迭代原始CSV文件?将其加载到pandas并使用numpy以某种方式对其进行矢量化(假设我有足够的内存......)?
  3. 编辑:通过撰写“邻居”,我希望明确表示我只想要一张无向图。对不起,如果这不明显。

2 个答案:

答案 0 :(得分:2)

如果我理解你的话,你想让图形表示为G(V,E),其中V和E是两组,其中 V ertices和 E dges

由于 E dges是无向的,你需要考虑某种方式来表示它们。要么你不关心他们的方向,要么总是检查两个方向中是否存在边缘,或者你是否规范它们,例如:通过对元组使用字母数字排序。

所以,我们假设您选择后者,那么E是一组元组,其中条目遵循严格的顺序

e = (v1, v2), v1 < v2.

通过此定义,您可以逐行处理文件,将ID添加到Set V,创建包含邻居(ID, neighbor)(neighbor, ID)的元组,取决于其字母数字订购,并将其添加到您的Set E

如果你坚持边缘的规范表示,Python会注意,Set中的边缘不会重复,因为它被定义为一组无序的唯一元素。 https://docs.python.org/2/library/sets.html

只要您可以假设您的文件是正确的,并且没有边缘,那就没有结束(因为缺少ID),您可以先创建边,然后再到达 - 一旦到达相应的边你会创建顶点 如果你不能坚持这个假设,你仍然可以用这种方式创建你的图形表示,你只需要在最后实现一些清理,再次迭代边集,检查是否有任何边缘在不知情的地方留下dangeling(指向一个不存在的顶点),并通过删除此边缘或创建顶点来处理此问题 - 无论什么都适合您的需要。

答案 1 :(得分:0)

编辑2 - 好的,无向图,你只想输出边和顶点:​​derM得到它。只要注意数据的大小 - 集合就会快速增长。最初是不是创建图表而不是提取边缘列表?