如何从pandas数据帧创建边缘列表?

时间:2017-07-09 01:16:17

标签: python pandas dataframe network-analysis

我有一个形式为 -

的pandas数据帧(df)
    Col1
A  [Green,Red,Purple]
B  [Red, Yellow, Blue]
C  [Brown, Green, Yellow, Blue]

我需要将其转换为边缘列表,即格式为的数据框:

Source    Target    Weight
  A         B         1
  A         C         1
  B         C         2

修改 请注意,新数据框的行数等于可能的成对组合的总数。此外,计算“重量”'列,我们只是找到两个列表之间的交集。例如,对于B& C,元素共享两种颜色:蓝色和黄色。因此,'重量'对应的行是2。

最快的方法是什么?原始数据框包含大约28,000个元素。

3 个答案:

答案 0 :(得分:5)

试试这个。工作不是很整洁。 PS:最后输出你可以调整它,我没有删除列并更改列名

components[0].dropFirst()

答案 1 :(得分:5)

首先,从数据帧开始:

In [823]: from itertools import combinations

In [824]: df = pd.DataFrame({'Col1': [['Green','Red','Purple'], ['Red', 'Yellow', 'Blue'], ['Brown', 'Green', 'Yellow', 'Blue']]}, index=['A',
     ...:  'B', 'C'])

In [827]: df['Col1'] = df.Col1.apply(lambda x: set(x))

In [828]: df
Out[828]: 
                           Col1
A          {Purple, Red, Green}
B           {Red, Blue, Yellow}
C  {Green, Yellow, Blue, Brown}

Col1中的每个列表都已转换为集合以有效地查找联合。接下来,我们将使用itertools.combinations创建df中所有行的成对组合:

In [845]: df1 = pd.DataFrame(data=list(combinations(df.index.tolist(), 2)), columns=['Src', 'Dst'])

In [849]: df1
Out[849]: 
  Src Dst
0   A   B
1   A   C
2   B   C

现在,应用一个函数来获取集合的并集并找到它的长度。 SrcDst列充当df的查找。

In [859]: df1['Weights'] = df1.apply(lambda x: len(df.loc[x['Src']]['Col1'].intersection(df.loc[x['Dst']]['Col1'])), axis=1)

In [860]: df1
Out[860]: 
  Src Dst  Weights
0   A   B        1
1   A   C        1
2   B   C        2

我建议在一开始就设置转换。每次动态将列表转换为集合都是昂贵且浪费的。

为了获得更多的加速,您可能希望将这些集合复制到新数据框中的两列,就像@Wen已经完成的那样,因为不断调用df.loc会降低它的速度一个档次。

答案 2 :(得分:2)

  • 获取一组数组
  • 使用np.triu_indices
  • 获得表示所有组合的成对索引
  • 使用&运算符来获取成对交叉点并通过理解获取长度
c = df.Col1.apply(set).values

i, j = np.triu_indices(c.size, 1)

pd.DataFrame(dict(
        Source=df.index[i],
        Target=df.index[j],
        Weight=[len(s) for s in c[i] & c[j]]
    ))

  Source Target  Weight
0      A      B       1
1      A      C       1
2      B      C       2