【问题标题】:Count appearance of each player by groups in Pandas在 Pandas 中按组计算每个玩家的出现次数
【发布时间】:2018-05-16 17:53:05
【问题描述】:

有一个球员在不同球队(组)中比赛的数据框,所以我需要计算每个球员与他只出现在他的球队球员的所有交集。

df = pd.DataFrame({ 'Team' : ['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'C'],
                      'Player' : ['Joe', 'Mike', 'Steve', 'Henry', 'Steve', 'Joe', 'Mike', 'Joe', 'Steve', 'Dan', 'Henry']
                  })
df
Out[6]:
Player  Team
0   Joe     A
1   Mike    A
2   Steve   A
3   Henry   B
4   Steve   B
5   Joe     B
6   Mike    C
7   Joe     C
8   Steve   C
9   Dan     C
10  Henry   C

输出必须是这样的。 PS我是手动做的,所以可能会出错。

Joe Mike 2
Joe Steve 3
Joe Henry 2
Joe Dan 1

Mike Joe 2
Mike Steve 2
Mike Dan 1
Mike Henry 1

Steve Joe 3
Steve Mike 2
Steve Henry 2
Steve Henry 1

Henry Steve 2
Henry Joe 2
Henry Mike 1
Henry Dan 1

Dan Steve 1 
Dan Mike 1
Dan Joe 1
Dan Henry 1

说明:乔已经出现在所有 3 支球队中,所以我只计算他与其他球员在他出现的 3 支球队之间的交集。同时,Dan 只在 C 队,我只考虑与 C 队其他球员的交集。

我尝试通过 groupby 和笛卡尔积连接来做到这一点,但不知道如何组合它。有人可以帮忙解决这个任务吗?

gp = df.groupby('Player')['Team'].apply(lambda x: "%s" % ', '.join(x)).to_frame()

index = pd.MultiIndex.from_product([gp.index, gp.index], names = ["a", "b"])

new_df = pd.DataFrame(index = index).reset_index()

【问题讨论】:

  • 我认为一个起点是df.merge(df, on='Team') 来获得你的交叉加入,然后应用.groupby(['Player_x', 'Player_y']).Team.size() 应该接近你想要的,你会想要从中删除相同的 X 和 Y 玩家。
  • @Jon Clements♦ 一切正常。留下评论,我会批准它。非常感谢。唯一的区别是需要删除相同的对(Joe-Joe m Henry-Henry 等)
  • 我刚回到办公桌前……我会看看我是否真的不能写出实际的答案 - 忍耐:)
  • 在任何方便的时候写下答案,我会批准它:)

标签: python-3.x pandas


【解决方案1】:

鉴于您的输入 DF:

df = pd.DataFrame({ 
    'Team' : ['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'C'],
    'Player' : ['Joe', 'Mike', 'Steve', 'Henry', 'Steve', 'Joe', 'Mike', 'Joe', 'Steve', 'Dan', 'Henry']
})

您可以在“团队”列中将其与自身合并以获得交叉加入,过滤掉两列中相同名称的玩家,然后获取配对之间的团队数量,例如:

new_df = (
    # Cartesian join dropping identical player pairs
    df.merge(df, on='Team')[lambda row: row.Player_x != row.Player_y]
    # Count unique number of overlaps and make column name a bit more usefu
    .groupby(['Player_x', 'Player_y']).Team.size().rename('shared_teams')
    # Optionally drop the index if not of use...
    .reset_index()
)

这会给你:

   Player_x Player_y  shared_teams
0       Dan    Henry             1
1       Dan      Joe             1
2       Dan     Mike             1
3       Dan    Steve             1
4     Henry      Dan             1
5     Henry      Joe             2
6     Henry     Mike             1
7     Henry    Steve             2
8       Joe      Dan             1
9       Joe    Henry             2
10      Joe     Mike             2
11      Joe    Steve             3
12     Mike      Dan             1
13     Mike    Henry             1
14     Mike      Joe             2
15     Mike    Steve             2
16    Steve      Dan             1
17    Steve    Henry             2
18    Steve      Joe             3
19    Steve     Mike             2

注意 - 在分组之后而不是之前删除重复的名称可能更有效。

【讨论】:

    猜你喜欢
    • 2016-12-20
    • 2016-06-02
    • 1970-01-01
    • 2017-12-17
    • 2011-12-27
    • 1970-01-01
    • 1970-01-01
    • 2021-07-02
    • 1970-01-01
    相关资源
    最近更新 更多