直接使用DataFrame的id列构造scipy.csr_matrix时出现索引越界错误的原因解析
DataFrame的id列构造scipy.csr_matrix时出现索引越界错误的原因解析
嘿,这个问题我之前也碰到过,核心是你没搞清楚scipy的CSR矩阵对索引的硬性要求~咱们一步步拆解:
两种构造方式的核心差异
首先明确一个关键规则:CSR矩阵要求传入的行/列索引必须是基于0的连续整数,而且最大值绝对不能超过你指定的shape对应维度的大小减一。
- 能正常运行的
X_works:你先把原始的user_id和item_id映射成了从0开始的连续索引(user_idx和item_idx)。比如item_idx的取值范围是0到M-1(M是item唯一值的数量),刚好匹配你指定的shape=(M,N)的第一维度大小,所以索引完全不会越界。 - 报错的
X_doesnt:你直接用了原始的item_id和user_id作为索引。这里的坑在于:原始id虽然是唯一的,但它们的取值范围不一定是0到M-1。比如你的测试代码里,item_id是np.random.randint(0,100,300),这意味着可能出现99这个值,但df["item_id"].nunique()得到的M可能只有97(随机生成大概率会漏掉几个数)。这时候你指定shape=(M,N),矩阵的行维度只有97,行索引最大只能是96,但你的item_id里有99,自然就触发了index 99 exceeds matrix dimension 97的错误。
为什么“id映射到唯一名称数量”还会报错?
你提到“id被映射到正好唯一名称的数量”,但这里的误解在于:原始id的最大值 ≠ 唯一值数量 - 1。比如你的item_id范围是0到100,共101个可能值,随机生成300条数据后,unique的数量可能是97,但最大的item_id依然可能是99,这时候99 > 97-1=96,必然越界。原始id的取值范围和唯一值数量是完全两回事:前者是id的数值区间,后者是不同id的个数。
怎么解决?
有两种可行方案:
- 继续用你已经实现的映射方法:把原始id转成从0开始的连续索引,确保索引最大值正好对应维度大小减一,完美匹配
shape参数,这也是最节省内存的方式。 - 如果一定要直接用原始id,那
shape的维度需要设为max(原始id)+1,而不是nunique()。但这种方式会产生大量空行/列(如果原始id不连续的话),非常浪费内存,只适合id本身就是连续0-based的场景。
比如在你的测试代码里,把X_doesnt的shape改成(df["item_id"].max()+1, df["user_id"].max()+1),它就能正常运行,但矩阵的大小会比X_works大很多,因为包含了那些没有对应数据的id行/列。
备注:内容来源于stack exchange,提问作者plotmaster473
相关产品推荐
相关产品推荐

