这是我的数据的非常简化的版本:
╔═════════╤═══════════╗
║ user_id │ module_id ║
╠═════════╪═══════════╣
║ 1 │ 1 ║
╟─────────┼───────────╢
║ 1 │ 1 ║
╟─────────┼───────────╢
║ 1 │ 2 ║
╟─────────┼───────────╢
║ 1 │ 1 ║
╟─────────┼───────────╢
║ 2 │ 2 ║
╟─────────┼───────────╢
║ 2 │ 1 ║
╟─────────┼───────────╢
║ 2 │ 2 ║
╟─────────┼───────────╢
║ 2 │ 2 ║
╟─────────┼───────────╢
║ 2 │ 1 ║
╟─────────┼───────────╢
║ 2 │ 2 ║
╚═════════╧═══════════╝
这是我要添加的列:
╔═════════╤═══════════╤════════════════════╗
║ user_id │ module_id │ repeated_module_id ║
╠═════════╪═══════════╪════════════════════╣
║ 1 │ 1 │ NaN ║
╟─────────┼───────────┼────────────────────╢
║ 1 │ 1 │ NaN ║
╟─────────┼───────────┼────────────────────╢
║ 1 │ 2 │ NaN ║
╟─────────┼───────────┼────────────────────╢
║ 1 │ 1 │ 1 ║
╟─────────┼───────────┼────────────────────╢
║ 2 │ 2 │ NaN ║
╟─────────┼───────────┼────────────────────╢
║ 2 │ 1 │ NaN ║
╟─────────┼───────────┼────────────────────╢
║ 2 │ 2 │ 2 ║
╟─────────┼───────────┼────────────────────╢
║ 2 │ 2 │ NaN ║
╟─────────┼───────────┼────────────────────╢
║ 2 │ 1 │ 1 ║
╟─────────┼───────────┼────────────────────╢
║ 2 │ 2 │ 2 ║
╚═════════╧═══════════╧════════════════════╝
即如果用户之前(但不是紧接在此之前)完成了一个模块,则会重复该模块。
我想用矢量化的熊猫来实现这一点,但是我看不到如何开始。
答案 0 :(得分:2)
IIUC,您可以尝试:
df=df.assign(repeated_module_id=df.loc[df.groupby('user_id')['module_id'].apply(lambda x:
x.ne(x.shift())&x.duplicated()),'module_id'])
user_id module_id repeated_module_id
0 1 1 NaN
1 1 1 NaN
2 1 2 NaN
3 1 1 1.0
4 2 2 NaN
5 2 1 NaN
6 2 2 2.0
7 2 2 NaN
8 2 1 1.0
9 2 2 2.0
答案 1 :(得分:2)
您可以在整个框架上使用duplicated
来同时检查user_id
和 module_id
,您不需要groupby
+ { {1}}。然后,就像根据您的初始帧进行遮罩一样简单。
apply
m1 = df['module_id'].ne(df['module_id'].shift())
m2 = df.duplicated(['user_id', 'module_id'])
df['module_id'].where(m1 & m2)
这应该比0 NaN
1 NaN
2 NaN
3 1.0
4 NaN
5 NaN
6 2.0
7 NaN
8 1.0
9 2.0
Name: module_id, dtype: float64
apply