【问题标题】:pandas: Find overlap of clubs熊猫:查找俱乐部的重叠
【发布时间】:2022-01-20 08:24:05
【问题描述】:

我收到一个(熊猫)数据框,告诉我有关人员和俱乐部的会员关系。我要查找的是任意两个俱乐部共有的成员数量。

示例输入:

Person Club
1      A
1      B
1      C
2      A
2      C
3      A
3      B
4      C

换句话说,A = {1,2,3},B = {1,3},C = {1,2,4}。

期望的输出:

Club 1  Club 2  Num_Overlaps
A       B       2
A       C       2
B       C       1

我当然可以编写计算这些数字的 python 代码,但我想肯定有一种更类似于数据帧的方式使用 groupby 左右来完成同样的事情。

【问题讨论】:

  • 请包含您的计算这些数字的python代码
  • Person 1 和Person 3 都在Club A 和B 中。第一行的重叠数不应该是2 吗?
  • @MichaelSzczesny 我可能已经将数据框读取到字典中,将俱乐部作为一组人,然后迭代成对的俱乐部并在 for 循环中计算它们的交集。我没有把它写下来,因为我认为这不是你应该这样做的方式,因为我想把数据放在最后的数据框中,因此是这个问题。
  • 谢谢@rchome,你当然是对的。相应地进行了编辑。

标签: python pandas


【解决方案1】:

您确实可以使用groupby 和一些集合操作来做到这一点。我还会使用itertools.combinations 来获取俱乐部对的列表。

import pandas as pd
from itertools import combinations

df = pd.DataFrame({'Person': [1, 1, 1, 2, 2, 3, 3, 4],
                   'Club': list('ABCACABC')})

members = df.groupby('Club').agg(set)
clubs = sorted(list(set(df.Club)))
overlap = pd.DataFrame(list(combinations(clubs, 2)),
                       columns=['Club 1', 'Club 2'])

def n_overlap(row):
    club1, club2 = row
    members1 = members.loc[club1, 'Person']
    members2 = members.loc[club2, 'Person']
    return len(members1.intersection(members2))

overlap['Num_Overlaps'] = overlap.apply(n_overlap, axis=1) 
overlap
    Club 1  Club 2  Num_Overlaps
0   A       B       2
1   A       C       2
2   B       C       1

请注意,您想要的输出有一个差异,但这可能是应该的,正如@rchome 在上面的评论中所指出的那样。

【讨论】:

  • 感觉有点不那么纯粹的数据帧,因此现在接受了另一个答案。但仍然从您的解决方案中学到了一些东西,谢谢!
  • 感谢您的反馈。我很高兴能帮上忙。
【解决方案2】:

首先,我将俱乐部上的数据框分组,以获得俱乐部中每个人的一组数据。

grouped = df.groupby("Club").agg({"Person": set}).reset_index()

  Club     Person
0    A  {1, 2, 3}
1    B     {1, 3}
2    C  {1, 2, 4}

然后,我创建了这个数据框的笛卡尔积。我没有 pandas 1.2.0,所以我无法使用 df.merge() 中提供的交叉连接。相反,我使用了这个答案中的想法:pandas two dataframe cross join

grouped["key"] = 0
product = grouped.merge(grouped, on="key", how="outer").drop(columns="key")

  Club_x   Person_x Club_y   Person_y
0      A  {1, 2, 3}      A  {1, 2, 3}
1      A  {1, 2, 3}      B     {1, 3}
2      A  {1, 2, 3}      C  {1, 2, 4}
3      B     {1, 3}      A  {1, 2, 3}
4      B     {1, 3}      B     {1, 3}
5      B     {1, 3}      C  {1, 2, 4}
6      C  {1, 2, 4}      A  {1, 2, 3}
7      C  {1, 2, 4}      B     {1, 3}
8      C  {1, 2, 4}      C  {1, 2, 4}

然后我过滤掉了 Club_x < Club_y 的对,因此它删除了重复的对。

filtered = product[product["Club_x"] < product["Club_y"]]

  Club_x   Person_x Club_y   Person_y
1      A  {1, 2, 3}      B     {1, 3}
2      A  {1, 2, 3}      C  {1, 2, 4}
5      B     {1, 3}      C  {1, 2, 4}

最后,我添加了具有重叠大小的列,并根据需要重命名了列。

result = filtered.assign(Num_Overlaps=filtered.apply(lambda row: len(row["Person_x"].intersection(row["Person_y"])), axis=1))
result = result.rename(columns={"Club_x": "Club 1", "Club_y": "Club 2"}).drop(["Person_x", "Person_y"], axis=1)

  Club 1 Club 2  Num_Overlaps
1      A      B             2
2      A      C             2
5      B      C             1

【讨论】:

    猜你喜欢
    • 2014-01-03
    • 1970-01-01
    • 1970-01-01
    • 2019-04-19
    • 1970-01-01
    • 2021-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多