我有下面的数据帧。
df = pd.DataFrame({'Player': [1,1,1,1,2,2,2,3,3,3,4,5], "Team": ['X','X','X','Y','X','X','Y','X','X','Y','X','Y'],'Month': [1,1,1,2,1,1,2,2,2,3,4,5]})
输入:
Player Team Month
0 1 X 1
1 1 X 1
2 1 X 1
3 1 Y 2
4 2 X 1
5 2 X 1
6 2 Y 2
7 3 X 2
8 3 X 2
9 3 Y 3
10 4 X 4
11 5 Y 5
数据框架由球员、他们所属的球队和月份组成。在给定的月份,同一个玩家可以有多个条目。有些球员在某个月从X队转会到Y队,有些球员根本不转会,有些球员直接加入Y队。
我正在寻找某个月从X团队转移到Y团队的总人数,输出应该如下所示。即转换的月份和转换的总计数。在这种情况下,玩家1、2在第2个月移动,玩家3在第3个月移动。玩家4和5没有移动。
预期输出:
Month Count
0 2 2
1 3 1
我可以用以下方式完成这项工作。
###find all the people who moved from Team X to Y###
s1 = df.drop_duplicates(['Team','Player'])
s2 = s1.groupby('Player').size().reset_index(name='counts')
s2 = s2[s2['counts']>1]
####Tie them to the original df so that I can find the month in which they moved###
s3 = s1.groupby("Player").last().reset_index()
s4 = s3[s3['Player'].isin(s2['Player'])]
s5 = s4.groupby('Month').size().reset_index(name='Count')
我确信还有比我在这里做的更好的方法。只是想寻求一些帮助来提高效率。
首先选择(1(改变团队但(2(不是玩家第一排的条目。然后计算每个月分组的大小。
mask = df["Team"].shift().ne(df["Team"]) & df["Player"].shift().eq(df["Player"])
out = df[mask].groupby("Month").size()
输出:
print(out) # a Series
Month
2 2
3 1
dtype: int64
# series to dataframe (optional)
out.to_frame(name="count").reset_index()
Month count
0 2 2
1 3 1
编辑:mask
中的第一个groupby
是多余的,因此已删除。
一个选项是在Player, Month
上自我合并,并检查移动的玩家:
s = df.drop_duplicates()
t = (s.merge(s.assign(Month=s.Month+1), on=['Player', 'Month'], how='right')
.assign(Count=lambda x: x.Team_x.eq('Y') & x.Team_y.eq('X'))
.groupby('Month', as_index=False)['Count'].sum()
)
print(t.loc[t['Count'] != 0])
输出:
Month Count
0 2 2
1 3 1