如何按数组交集对 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 进行分组。例如,行 0
和 1
都包含 foo.ca
,行 1
和 2
都包含 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]
假设我有一个如下所示的 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 进行分组。例如,行 0
和 1
都包含 foo.ca
,行 1
和 2
都包含 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]