如何按数组交集对 pandas 数据框进行分组

How to group a pandas dataframe by array intersection

假设我有一个如下所示的 DataFrame

  UUID             domains
0  asd   [foo.com, foo.ca]
1  jkl    [foo.ca, foo.fr]
2  xyz            [foo.fr]
3  iek  [bar.com, bar.org]
4  qkr           [bar.org]
5  kij          [buzz.net]

我怎样才能把它变成这样的东西?

  UUID
0  [asd, jkl, xyz]
1  [iek, qkr]
2  [kij]

我想对任何其他 domains 列中存在任何域的所有 UUID 进行分组。例如,行 01 都包含 foo.ca,行 12 都包含 foo.fr,因此应该组合在一起。

我的数据集有数百万行,所以我不能暴力破解它。

我们可以先做explode再用networkx

import networkx as nx
s = df.explode('domains')
G = nx.from_pandas_edgelist(s, 'UUID', 'domains')
out = pd.Series([[y for y in x if y not in s.domains.tolist()] for x in [*nx.connected_components(G)]])
Out[209]: 
0    [xyz, jkl, asd]
1         [iek, qkr]
2              [kij]
dtype: object

假设以下输入域作为列表:

df = pd.DataFrame({'UUID': ['asd', 'jkl', 'xyz', 'iek', 'qkr', 'kij'],
                   'domains': [['foo.com', 'foo.ca'], ['foo.ca', 'foo.fr'], ['foo.fr'], ['bar.com', 'bar.org'], ['bar.org'], ['buzz.net']]}
                 )

你的问题是图形问题。您想找到断开连接的子图的根:

这很容易通过 networkx 实现。

# transform dataframe into graph
import networkx as nx
G = nx.from_pandas_edgelist(df.explode('domains'),
                            source='UUID', target='domains',
                            create_using=nx.DiGraph)

# split the subgraphs (weakly_connected) and find the roots (degree: 0)
# the output is a generator
groups = ([n for n,g in G.subgraph(c).in_degree if g==0]
          for c in nx.weakly_connected_components(G))

# transform the generator to Series
s = pd.Series(groups)

输出:

0    [asd, jkl, xyz]
1         [iek, qkr]
2              [kij]