【问题标题】:How to group a pandas dataframe by array intersection如何通过数组交集对熊猫数据框进行分组
【发布时间】:2022-11-10 11:00:00
【问题描述】:

假设我有一个如下所示的 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,因此应该组合在一起。

我的数据集的大小是数百万行,所以我不能强行使用它。

【问题讨论】:

  • 请提供 DataFrame 构造函数,格式不明确(字符串?列表?)

标签: python pandas dataframe networkx graph-theory


【解决方案1】:

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

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]

【讨论】:

  • 太谢谢了。这与我的想法一致。我将用更多的上下文以及到目前为止我尝试过的内容来更新这个问题。这将如何表现?我有大约 2000 万行数据要处理。我想我可以通过按domain 列对分解的数据框进行分组并聚合id 列来减小数据的大小。我可以丢弃所有只有一个 ID 的行,因为它们没有任何关系。
  • @Iain 没有实际数据很难回答。这当然取决于您拥有多少组、每组节点、单行等。你为什么不试试 1% 的样本,然后 10% 的样本,看看它是否可以扩展?我当然会对反馈感兴趣;)
  • 很抱歉在这里回复您的延迟。我拥有的数据集大约有 15M 行,平均 domains 列有 3 个项目。当加载到 DataFrame 中时,它的内存大约为 2GB。在 r5.2xl EC2 实例(64GB RAM,8vCPU)上运行示例代码大约需要 8 分钟。在此期间它消耗了大约 36GB。
【解决方案2】:

我们可以先使用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

【讨论】:

  • 谢谢。这将如何扩展到处理数百万行?
猜你喜欢
  • 2016-12-17
  • 1970-01-01
  • 2017-10-15
  • 2022-01-25
  • 2021-11-02
  • 2018-02-07
  • 1970-01-01
  • 2019-07-10
  • 2013-02-28
相关资源
最近更新 更多