我有一个df:
import pandas as pd
df = pd.DataFrame({'user_id': [1,1,2,1,2,1,2,3], 'movie_id': ['35','120','898','546','989','42','546','35'],
'time':['1.7','2.1','1.3','2.4','1.4','7.0','2.1','1.1']})
看起来像这样:
user_id movie_id time
1 35 1,7
1 120 2.1
2 898 1.3
1 546 2.4
2 989 1.4
1 42 7.0
2 546 2.1
3 35. 1.1
我的目标是按user_id分组,按时间排序,并用“ 1”填充新列,但每个组中的第一行除外-“时间”列显示自上次点击以来经过的秒数。 最终,我应该获得这样的输出,其中包含用户在活动电影之前评分的最后一部电影的指示器:
user_id movie_id time last_rated
1 35 1.7 0
1 120 2.1 1
2 898 1.3 0
1 546 2.4 1
2 989 1.4 1
1 42 7.0 1
2 546 2.1 1
3 35 1.1 0
我已经尝试了group_by,shift,cumsum,但仍然无法获得所需的输出。任何帮助将不胜感激!
答案 0 :(得分:2)
可以使用cumcount()
和np.where()
df['last_rated'] = np.where(df.groupby('user_id').cumcount() == 0, 0, 1)
或(按照下面的@coldspeed)
df.groupby('user_id').cumcount().astype(bool).astype(int)
输出
user_id movie_id time last_rated
0 1 35 1.7 0
1 1 120 2.1 1
2 2 898 1.3 0
3 1 546 2.4 1
4 2 989 1.4 1
5 1 42 7.0 1
6 2 546 2.1 1
7 3 35 1.1 0
您可以预先使用sort_values
来确保您拥有正确的分类条件。但是,如果您想保持df
不变,可以在组内进行排序:
g = df.groupby('user_id', as_index=False).apply(lambda x: x.sort_values(by='time')).groupby('user_id').cumcount().reset_index(level=0,drop=True)
df['l'] = (g/g).fillna(0)
答案 1 :(得分:1)
您可以将GroupBy
与transform
一起使用min
和user_id
,以df['time']
计算一系列最小值。然后针对bool
检查是否相等,并将int
转换为g = df.groupby('user_id')['time'].transform('min')
df['last_rated'] = (df['time'] != g).astype(int)
。
time
假设您的数据框已经按user_id
的顺序对每个GroupBy
进行了排序,则可以更有效地将'first'
与g = df.groupby('user_id')['time'].transform('first')
一起使用:
print(df)
user_id movie_id time last_rated
0 1 35 1.7 0
1 1 120 2.1 1
2 2 898 1.3 0
3 1 546 2.4 1
4 2 989 1.4 1
5 1 42 7.0 1
6 2 546 2.1 1
7 3 35 1.1 0
结果:
{{1}}