提前感谢:
我试图在多对多关系表中生成一个组标识符,该表有2列定义父实体和子实体的ID:
以下示例数据框:(父(p)和子(c))
df = pd.DataFrame(np.array([[1,7],[1,3],[1,4],[3,2],[5,1],[6,0]]))
df.columns= ['p', 'c']
表如下所示:
p c
1 7
1 3
1 4
3 2
5 1
6 0
我试图在一个组中获取所有直接和间接链接的记录。例如:
所以我想为所有相关记录生成一个ID。如果父记录6与任何记录无关,我会将其移动到另一个组,样本结果如下:
p c grp
1 7 A
1 3 A
1 4 A
3 2 A
5 1 A
6 0 B
我目前的思维方式:
对于每条记录,如果它还没有组:
我不确定这是否是正确的方法,它似乎是不必要的慢,我必须将链中的所有父记录传递给子记录,以便它不执行同样搜索已搜索的结果。
如果有人能给我一个更好的解决方案,我真的很感激。 :)
答案 0 :(得分:2)
您可以查看networkx
import networkx as nx
G=nx.from_pandas_dataframe(df, 'c', 'p')
l=list(nx.connected_components(G))
dfmap=pd.DataFrame.from_dict(l)
dfmap.index=['B','A']
dfmap=dfmap.stack()
d=dict(list(zip(dfmap.values.astype(int),dfmap.index.get_level_values(0))))
df['grp']=df.replace(d).p
df
Out[14]:
p c grp
0 1 7 A
1 1 3 A
2 1 4 A
3 3 2 A
4 5 1 A
5 6 0 B
更多信息
import matplotlib.pyplot as plt
nx.draw(G)
答案 1 :(得分:0)
我会发布我的解决方案,因为它更快(对于这个小数据集)并希望有人能提高它的效率。
import netowrkx as nx
import pandas as pd
df = pd.DataFrame(np.array([[1,7],[1,3],[1,4],[3,2],[5,1],[6,0]]))
df.columns= ['p', 'c']
G = nx.from_pandas_dataframe(df, 'p','c')
subgraphs = list(nx.connected_components(G))
grouplist = list('BA')
def defineGrouping(x):
return grouplist[[n for n,i in enumerate(subgraphs) if x in i][0]]
df['grp'] = df.c.map(defineGrouping)
df
输出:
p c grp
0 1 7 A
1 1 3 A
2 1 4 A
3 3 2 A
4 5 1 A
5 6 0 B
@ Wen的方法将connected_components转换回pandas dataframe
100个循环,最佳3:每循环6.47 ms
这种使用列表理解和枚举的方法:
1000个循环,最佳3:每循环1.14毫秒