Pandas 计数组
Pandas count over groups
我有一个 pandas 数据框,如下所示:
ID round player1 player2
1 1 A B
1 2 A C
1 3 B D
2 1 B C
2 2 C D
2 3 C E
3 1 B C
3 2 C D
3 3 C A
数据框包含体育比赛结果,其中 ID
列表示一场比赛,round
列表示每场比赛的轮次,player1
和 player2
列包含在各自的 round
.
中互相对抗的玩家的名字
我现在想累计参加锦标赛的次数,比方说,玩家 A
。在伪代码中,这意味着:如果姓名为 A
的玩家在每次锦标赛 ID
中出现在 player1
或 player2
列中,则将计数器加 1。
结果应如下所示(注意:在我的示例中,玩家 A
确实以 ID
s 1 和 3 参加了锦标赛):
ID round player1 player2 playerAparticipated
1 1 A B 1
1 2 A C 1
1 3 B D 1
2 1 B C 0
2 2 C D 0
2 3 C E 0
3 1 B C 2
3 2 C D 2
3 3 C A 2
我目前的状态是,我添加了一个包含值 1
或 0
的 "helper" 列,表示如果相应玩家参加了比赛:
ID round player1 player2 helper
1 1 A B 1
1 2 A C 1
1 3 B D 1
2 1 B C 0
2 2 C D 0
2 3 C E 0
3 1 B C 1
3 2 C D 1
3 3 C A 1
我认为我只需要最后一步,例如巧妙地使用 cumsum()
以所需方式计算 helper
列。但是,我还没有想出解决办法。
我认为你需要:
drop_duplicates
by column ID
first and then set_index
- 通过
boolean indexing
, cumsum
and last reindex
筛选出 0
个值,以添加 0
以弥补缺失的索引值
- 新专栏由
map
创建
df1 = df.drop_duplicates('ID').set_index('ID')
s = df1.loc[df1['helper'] != 0, 'helper'].cumsum().reindex(index=df1.index, fill_value=0)
df['playerAparticipated'] = df['ID'].map(s)
print (df)
ID round player1 player2 helper playerAparticipated
0 1 1 A B 1 1
1 1 2 A C 1 1
2 1 3 B D 1 1
3 2 1 B C 0 0
4 2 2 C D 0 0
5 2 3 C E 0 0
6 3 1 B C 1 2
7 3 2 C D 1 2
8 3 3 C A 1 2
而不是 map
可以使用 join
和 rename
:
df = df.join(s.rename('playerAparticipated'), on='ID')
print (df)
ID round player1 player2 helper playerAparticipated
0 1 1 A B 1 1
1 1 2 A C 1 1
2 1 3 B D 1 1
3 2 1 B C 0 0
4 2 2 C D 0 0
5 2 3 C E 0 0
6 3 1 B C 1 2
7 3 2 C D 1 2
8 3 3 C A 1 2
与@jezrael 类似的方法,我做的有点慢:)。
首先,将 ID
移动到您的索引中:
df = df.reset_index().set_index(['index','ID'])
# round player1 player2 helper
# index ID
# 0 1 1 A B 1
# 1 1 2 A C 1
# 2 1 3 B D 1
# 3 2 1 B C 0
# 4 2 2 C D 0
# 5 2 3 C E 0
# 6 3 1 B C 1
# 7 3 2 C D 1
# 8 3 3 C A 1
接下来,过滤掉helper
为0的行,得到锦标赛累计总和ID
,并将结果赋值给一个变量:
tournament_count = df[df['helper'] > 0].groupby(['ID','helper']).first().reset_index(level=1)['helper'].cumsum().rename("playerAparticipated")
# ID
# 1 1
# 3 2
最后,用 df:
加入 tournament_count
DataFrame
df.join(tournament_counts, how="left").fillna(0)
# round player1 player2 helper tournament_counts
# index ID
# 0 1 1 A B 1 1.0
# 1 1 2 A C 1 1.0
# 2 1 3 B D 1 1.0
# 3 2 1 B C 0 0.0
# 4 2 2 C D 0 0.0
# 5 2 3 C E 0 0.0
# 6 3 1 B C 1 2.0
# 7 3 2 C D 1 2.0
# 8 3 3 C A 1 2.0
我有一个 pandas 数据框,如下所示:
ID round player1 player2
1 1 A B
1 2 A C
1 3 B D
2 1 B C
2 2 C D
2 3 C E
3 1 B C
3 2 C D
3 3 C A
数据框包含体育比赛结果,其中 ID
列表示一场比赛,round
列表示每场比赛的轮次,player1
和 player2
列包含在各自的 round
.
我现在想累计参加锦标赛的次数,比方说,玩家 A
。在伪代码中,这意味着:如果姓名为 A
的玩家在每次锦标赛 ID
中出现在 player1
或 player2
列中,则将计数器加 1。
结果应如下所示(注意:在我的示例中,玩家 A
确实以 ID
s 1 和 3 参加了锦标赛):
ID round player1 player2 playerAparticipated
1 1 A B 1
1 2 A C 1
1 3 B D 1
2 1 B C 0
2 2 C D 0
2 3 C E 0
3 1 B C 2
3 2 C D 2
3 3 C A 2
我目前的状态是,我添加了一个包含值 1
或 0
的 "helper" 列,表示如果相应玩家参加了比赛:
ID round player1 player2 helper
1 1 A B 1
1 2 A C 1
1 3 B D 1
2 1 B C 0
2 2 C D 0
2 3 C E 0
3 1 B C 1
3 2 C D 1
3 3 C A 1
我认为我只需要最后一步,例如巧妙地使用 cumsum()
以所需方式计算 helper
列。但是,我还没有想出解决办法。
我认为你需要:
drop_duplicates
by columnID
first and thenset_index
- 通过
boolean indexing
,cumsum
and lastreindex
筛选出0
个值,以添加0
以弥补缺失的索引值 - 新专栏由
map
创建
df1 = df.drop_duplicates('ID').set_index('ID')
s = df1.loc[df1['helper'] != 0, 'helper'].cumsum().reindex(index=df1.index, fill_value=0)
df['playerAparticipated'] = df['ID'].map(s)
print (df)
ID round player1 player2 helper playerAparticipated
0 1 1 A B 1 1
1 1 2 A C 1 1
2 1 3 B D 1 1
3 2 1 B C 0 0
4 2 2 C D 0 0
5 2 3 C E 0 0
6 3 1 B C 1 2
7 3 2 C D 1 2
8 3 3 C A 1 2
而不是 map
可以使用 join
和 rename
:
df = df.join(s.rename('playerAparticipated'), on='ID')
print (df)
ID round player1 player2 helper playerAparticipated
0 1 1 A B 1 1
1 1 2 A C 1 1
2 1 3 B D 1 1
3 2 1 B C 0 0
4 2 2 C D 0 0
5 2 3 C E 0 0
6 3 1 B C 1 2
7 3 2 C D 1 2
8 3 3 C A 1 2
与@jezrael 类似的方法,我做的有点慢:)。
首先,将 ID
移动到您的索引中:
df = df.reset_index().set_index(['index','ID'])
# round player1 player2 helper
# index ID
# 0 1 1 A B 1
# 1 1 2 A C 1
# 2 1 3 B D 1
# 3 2 1 B C 0
# 4 2 2 C D 0
# 5 2 3 C E 0
# 6 3 1 B C 1
# 7 3 2 C D 1
# 8 3 3 C A 1
接下来,过滤掉helper
为0的行,得到锦标赛累计总和ID
,并将结果赋值给一个变量:
tournament_count = df[df['helper'] > 0].groupby(['ID','helper']).first().reset_index(level=1)['helper'].cumsum().rename("playerAparticipated")
# ID
# 1 1
# 3 2
最后,用 df:
加入tournament_count
DataFrame
df.join(tournament_counts, how="left").fillna(0)
# round player1 player2 helper tournament_counts
# index ID
# 0 1 1 A B 1 1.0
# 1 1 2 A C 1 1.0
# 2 1 3 B D 1 1.0
# 3 2 1 B C 0 0.0
# 4 2 2 C D 0 0.0
# 5 2 3 C E 0 0.0
# 6 3 1 B C 1 2.0
# 7 3 2 C D 1 2.0
# 8 3 3 C A 1 2.0