R语言如何将行索引列表表示的稀疏二值矩阵转为列索引列表
稀疏矩阵行索引列表转列索引列表的高效实现
不需要手写大量循环,R里用基础内置函数就能完成向量化实现,底层走C级计算,哪怕是大尺寸稀疏矩阵处理速度也很快。
实现思路
本质是反转「行号→该行非零元列号」的映射关系:
- 先把嵌套的行索引列表打平,生成两个等长向量:一个记录每个非零元对应的行号,一个记录每个非零元对应的列号
- 再按列号对行号分组,得到的结果就是目标列索引列表
全程不需要写R层面的显式for/while循环。
具体代码
首先用题目给出的3×3矩阵做示例,先构造输入:
# 示例输入M_row,对应题目给出的3×3矩阵 M_row <- list( c(1, 2), c(2), c(3) )
核心转换代码仅3行:
# 生成每个非零元对应的行号 row_ids <- rep(seq_along(M_row), lengths(M_row)) # 打平得到每个非零元对应的列号 col_ids <- unlist(M_row, use.names = FALSE) # 按列号分组得到列索引列表 M_col <- split(row_ids, col_ids)
如果矩阵存在全零列,需要保证输出列表长度和矩阵列数一致,可以加一步补全:
# 若已知矩阵列数为n,可直接替换为n_cols <- n n_cols <- max(col_ids) M_col <- M_col[as.character(seq_len(n_cols))]
运行后得到的M_col和题目要求的目标输出完全一致:
> M_col $`1` [1] 1 $`2` [1] 1 2 $`3` [1] 3
超大规模矩阵的优化方案
如果要处理百万级以上非零元的超大型稀疏矩阵,可以直接用Matrix包的稀疏矩阵结构转置实现,内存和速度表现更好:
library(Matrix) # 直接构建稀疏矩阵 sp_mat <- sparseMatrix(i = row_ids, j = col_ids) # 转置后提取非零元索引,按列拆分即可 t_sp <- as(t(sp_mat), "nMatrix") M_col <- split(t_sp@i + 1, rep(seq_len(ncol(t_sp)), diff(t_sp@p)))
注意事项
- 不要用嵌套
lapply/sapply遍历的写法,这类写法本质还是在R层面做循环,数据量上来之后速度会比上述向量化写法慢几十到上百倍。 - 如果输入矩阵的列索引不是从1开始连续编号,需要先做列号的连续化映射,避免分组出错。
内容的提问来源于stack exchange,提问作者Zhuzhu
相关产品推荐
相关产品推荐

