检查用户是否在MovieLens数据帧中看过电影



我试图创建一个数据帧,其中每个用户将有一个具有二进制分类的所有电影的列表,无论用户是否看过这部电影。RN我使用MovieLens小(ZIP),并试图得到这样的结果:

1  2  3  4  5  6  etc
1  0  0  1  1  0  1  etc
2  1  0  0  0  1  1  etc
3  0  1  1  0  0  1  etc

原始dataframe如下:

movieId  title 
0   1        Toy Story (1995)    
1   2        Jumanji (1995)
2   3        Grumpier Old Men (1995)    
3   4        Waiting to Exhale (1995)   
userId  movieId     rating  timestamp
0   1       1           4.0     964982703
1   1       3           4.0     964981247
2   1       6           4.0     964982224
3   1       47          5.0     964983815
4   1       50          5.0     964982931

其中索引为用户id,列为电影id。我尝试使用如下的列表推导式来解决这个问题:

pd.DataFrame(data=[[1 if movie_id in ratings_df[ratings_df["userId"] == user_id]["movieId"] else 0 for movie_id in tqdm(range(1, last_movie + 1))] for user_id in range(1, last_user + 1)], columns=movie_columns) 

但是这个工作方式太慢了。

使用pd.crosstab:

对于这个示例:

userId  movieId  rating   timestamp
85255     554     1947     5.0   944900238
21229     140     1262     5.0   942841394
40791     275     2580     4.0  1049078929
73989     474     3135     4.0  1115125983
73989     474     3135     4.0  1115125983  # dupe
22434     153      520     2.0  1525552333
22434     153      520     2.0  1525552333  # dupe

你可以使用:

>>> pd.crosstab(df['userId'], df['movieId']).astype(bool).astype(int)
movieId  520   1262  1947  2580  3135
userId
140         0     1     0     0     0
153         1     0     0     0     0
275         0     0     0     1     0
474         0     0     0     0     1
554         0     0     1     0     0

仅用于整个小数据集([100836行x 4列])的信息

# Solution proposed from duplicated link
>>> %timeit pd.get_dummies(df.set_index('userId')['movieId'])
9.73 s ± 158 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# Proposed solution here
>>> %timeit pd.crosstab(df['userId'], df['movieId']).astype(bool).astype(int)
5.95 s ± 307 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

最新更新