quanteda中dfm_lookup出现100%稀疏性问题及函数差异咨询
关于quanteda中dfm_lookup稀疏性问题及相关函数差异解析
1. dfm_lookup出现100%稀疏性的原因
问题核心是输入dfm_lookup的DFM已经是词典聚合后的结果,而非原始词项的DFM:
- 你先执行了
dtm <- dfm(tokens(corp2), dictionary = lex),这个操作生成的DFM列是词典的topic(如cardiac、non_specific),而非原始文本中的单个词项(如pericarditis、heart)。 - 随后用
dfm_lookup(dtm, lex, valuetype = "glob")时,函数会在dtm的特征(列名)中查找词典里的关键词,但此时dtm的列名是topic名称,完全没有匹配项,因此结果全为0,显示100%稀疏。
正确的做法是给dfm_lookup传入原始词项的DFM,而非聚合后的DFM:
# 生成原始词项的DFM(未按词典聚合) dtm_raw <- dfm(corp2) # 对原始DFM执行词典匹配 dtm_lu <- dfm_lookup(dtm_raw, lex, valuetype = "glob") print(dtm_lu)
2. 两个语句的核心差异
dtm <- dfm(tokens(corp2), dictionary = lex)
- 作用:直接从tokens对象生成词典聚合后的DFM,一步完成分词到词典匹配的全流程。
- 输入:tokens对象+词典,输出的DFM列是词典的topic分类。
dtm_lu <- dfm_lookup(dtm, lex, valuetype = "glob")
- 作用:对已存在的DFM进行二次聚合,将DFM中匹配词典关键词的特征(列)归到对应的topic下。
- 输入:必须是包含原始词项的DFM(而非聚合后的),否则无法匹配到关键词。
简单说:前者是"从分词直接生成聚合DFM",后者是"对已有词项DFM做词典聚合",两者适用场景不同,但最终正确执行后结果一致。
3. dfm(tokens(corp2), dictionary = lex)的运行逻辑
- 分词校验:接收预处理后的tokens对象
corp2,遍历每个文档的词项; - 词典匹配:检查每个词项是否匹配词典
lex中的任意关键词(默认用valuetype = "glob"匹配规则,支持通配符); - 计数聚合:将匹配到同一topic的词项计数累加,比如文档中同时出现
pericarditis和heart,都会计入cardiac列的计数; - 结果输出:生成以文档为行、词典topic为列的DFM,自动过滤未匹配到词典的词项。
修正后的完整示例代码
doc <- data.frame(symptoms = c("patient trouble breathing", "breathlessness", "heart palpitations", "elevated troponin", "chest tightness, pericarditis", "patient drowsy, headaches, low blood pressure", "tummy pain, vomiting", "heart attack", "edema, achypnea")) # 创建语料库并预处理 corp <- corpus(doc, text_field = 'symptoms') corp2 <- corp %>% tokens(remove_punct = T, remove_numbers = T, remove_symbols = T) %>% tokens_tolower() %>% tokens_remove(stopwords('en')) # 构建词典 terms <- structure(list(keywords = c("myocarditis", "pericarditis", "heart","heart-attack", "chest-pain", "tightness","tummy", "irritability", "vomiting", "tachypnea", "achypnea", "tachypnoea", "lethargy", "drowsiness", "drowsy"), topic = c("cardiac", "cardiac","cardiac", "cardiac","cardiac", "non_specific", "non_specific", "non_specific","non_specific","non_specific", "non_specific","non_specific", "children", "children","children")) ,class = "data.frame", row.names = c(NA, -15L)) lex <- split(terms$keywords, terms$topic) %>% dictionary() # 方法1:直接从tokens生成聚合DFM dtm <- dfm(tokens(corp2), dictionary = lex) print(dtm) # 方法2:先生成原始DFM,再用dfm_lookup聚合 dtm_raw <- dfm(corp2) dtm_lu <- dfm_lookup(dtm_raw, lex, valuetype = "glob") print(dtm_lu) # 查看未匹配项(需传入原始DFM) dfm_lookup(dtm_raw, lex, nomatch = "_UNMATCHED")
内容的提问来源于stack exchange,提问作者Magnetar
相关产品推荐
相关产品推荐

