Pandas中一列中从一个值到另一个值的转换计数



我有下面的数据帧。

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

最新更新