我有一个形式为 -
的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个元素。
答案 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
现在,应用一个函数来获取集合的并集并找到它的长度。 Src
和Dst
列充当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