DocumentTermMatrix转0/1因子时apply处理结果异常排查
错误原因
代码的核心问题是直接将DocumentTermMatrix类型对象传入apply()处理。tm包生成的DocumentTermMatrix属于simple_triplet_matrix类稀疏矩阵,采用「行索引、列索引、非零值」三元组结构存储,并非R基础的稠密矩阵对象。apply()没有适配这类稀疏矩阵的处理逻辑,传入后不会按预期逐列提取每个文档对应词项的词频,反而会错误读取稀疏矩阵的内部存储结构,叠加R的向量自动循环补齐规则,最终所有非零值会被错误堆到第一行,其余位置全部补0,就出现了第一行全为"yes"、其余行几乎全为"no"的异常结果,和原词频分布完全无关。
正确实现方法
优先用tm包内置函数处理,效率更高,对稀疏矩阵的内存友好度也更好:
方法1:使用tm内置二值化函数(推荐)
tm包自带词频二值转换的权重函数,不需要自己写逐列判断逻辑:
# 一步完成DTM的二值转换,所有非零值统一置为1 dtm_binary <- weightBin(text_freq_word_train) # 如果需要转成要求的因子矩阵,转成普通矩阵后做因子映射即可 dtm_binary_mat <- as.matrix(dtm_binary) dtm_factor <- factor( dtm_binary_mat, levels = c(0, 1), labels = c("no", "yes") ) # 恢复原矩阵维度,对齐行名(文档ID)、列名(词项) dim(dtm_factor) <- dim(dtm_binary_mat) rownames(dtm_factor) <- rownames(text_freq_word_train) colnames(dtm_factor) <- colnames(text_freq_word_train)
方法2:手动转换(需先转稠密矩阵)
如果要自己实现二值判断逻辑,必须先把稀疏DTM转为基础的数值稠密矩阵,再做向量化运算,不需要逐列用apply(向量化运算效率远高于逐列循环):
# 第一步:先把稀疏DTM转为基础数值矩阵 dtm_mat <- as.matrix(text_freq_word_train) # 第二步:向量化完成二值转换,>0置1否则置0 dtm_binary <- 1 * (dtm_mat > 0) # 第三步:转为指定水平的因子,恢复维度和行列名 dtm_factor <- factor( dtm_binary, levels = c(0,1), labels = c("no","yes") ) dim(dtm_factor) <- dim(dtm_binary) rownames(dtm_factor) <- rownames(dtm_mat) colnames(dtm_factor) <- colnames(dtm_mat)
注意:如果DTM维度很高(文档、词项量级极大),直接转稠密矩阵可能占用大量内存,优先选择方法1的内置函数处理。
内容的提问来源于stack exchange,提问作者Mansoor
相关产品推荐
相关产品推荐

