如何将Pandas DataFrame高效转换为适配Surprise的元组列表?
高效把Pandas DataFrame转成Surprise所需的元组列表
嘿,刚好我对Surprise的自定义数据加载格式门儿清,给你分享几个不用傻循环的高效实现方法,适配你说的**(用户ID, 物品ID, 评分)**元组格式:
方法一:用Pandas的stack()(最简洁省心)
如果你的DataFrame是行存用户、列存物品、单元格是评分的结构,stack()简直是为这个场景量身定做的:
import pandas as pd import numpy as np # 先整个示例DataFrame模拟你的数据 ratings_df = pd.DataFrame( np.random.randint(1, 6, (3, 4)), index=["user_001", "user_002", "user_003"], # 用户ID columns=["item_001", "item_002", "item_003", "item_004"] # 物品ID ) # 一步转成目标格式 surprise_ready_data = list(ratings_df.stack().reset_index().itertuples(index=False, name=None)) # 输出大概是这样:[('user_001', 'item_001', 4), ('user_001', 'item_002', 2), ...]
拆解下逻辑:
ratings_df.stack():把列维度的物品ID压到行维度,变成一个带(用户ID, 物品ID)多级索引的Series,值就是对应的评分。reset_index():把多级索引拆成普通列,得到三列数据:用户、物品、评分。itertuples(...):直接生成无冗余信息的元组迭代器,转成列表就搞定了。而且这个方法会自动跳过DataFrame里的缺失值(比如NaN),非常贴心。
方法二:NumPy向量化操作(超大数据集首选)
如果你的数据量特别大(比如百万级以上的评分矩阵),直接用NumPy操作底层数组会更快,减少Pandas的对象开销:
# 批量生成用户ID数组:每个用户ID重复物品列的次数 user_ids = ratings_df.index.values.repeat(ratings_df.shape[1]) # 批量生成物品ID数组:物品ID循环重复用户行的次数 item_ids = np.tile(ratings_df.columns.values, ratings_df.shape[0]) # 把评分矩阵扁平化 ratings = ratings_df.values.flatten() # 组合成元组列表 surprise_ready_data = list(zip(user_ids, item_ids, ratings)) # 如果有缺失值,记得先过滤掉: mask = ~np.isnan(ratings) surprise_ready_data = list(zip(user_ids[mask], item_ids[mask], ratings[mask]))
选哪个?
- 中小规模数据:优先选
stack(),代码短、可读性强,完全够用。 - 超大矩阵:选NumPy的方法,速度会快不少,毕竟是直接操作数组,没有Pandas的中间层开销。
内容的提问来源于stack exchange,提问作者maudidi
相关产品推荐
相关产品推荐

