如何用lapply结合data.table批量生成症状关键词匹配列?
批量为data.table添加关键词匹配列的优雅实现
需求说明
现有一份症状记录数据表,需要根据预设的关键词分类列表,批量添加对应列,标记每条记录的症状文本是否包含对应分类下的任意关键词,替代逐列手动赋值的繁琐写法。
原始数据表
DT <- data.table(no = c(1, 2, 3), symptom = c("headache and numbness", "tachycardia, sometimes headahce", "breath difficulty with limb numbness"))
关键词分类列表
key.word <- list( head = c("head", "headache"), chest = c("breath", "tachycardia", "palpitaion") )
期望结果
最终需要得到包含新增匹配标记列的数据表:
result <- data.table(no = c(1, 2, 3), symptom = c("headache and numbness", "tachycardia, sometimes headahce", "breath difficulty with limb numbness"), head = c(T, T, F), chest = c(F, T, T))
现有逐列实现方式
目前通过逐列赋值的方式实现,但扩展性较差:
DT[symptom %like% paste0(head, collapse = "|"), head := T] DT[symptom %like% paste0(chest, collapse = "|"), chest := T]
优雅的批量实现方案
以下几种方式利用lapply结合data.table的特性,实现批量处理:
方法一:简洁的多列一次性赋值
直接遍历关键词列表,生成每个分类的匹配逻辑向量,一次性添加所有新列:
DT[, c(names(key.word)) := lapply(key.word, function(kw) { symptom %like% paste0(kw, collapse = "|") })]
这种写法无需提前初始化列,%like%会直接返回对应长度的逻辑向量,data.table会自动将这些向量作为新列添加到表中。
方法二:先初始化再批量更新
如果需要先将所有标记列初始化为FALSE,再对匹配的行更新为TRUE,可以这样写:
# 初始化所有标记列为FALSE DT[, names(key.word) := FALSE] # 遍历每个关键词分类,更新匹配行 lapply(names(key.word), function(col_name) { DT[symptom %like% paste0(key.word[[col_name]], collapse = "|"), (col_name) := TRUE] })
方法三:用set函数提升大数据集效率
当处理超大数据表时,使用data.table的set函数可以避免不必要的副本创建,提升运行效率:
# 初始化标记列 DT[, names(key.word) := FALSE] # 遍历更新 lapply(names(key.word), function(col_name) { match_rows <- which(DT$symptom %like% paste0(key.word[[col_name]], collapse = "|")) set(DT, i = match_rows, j = col_name, value = TRUE) })
以上三种方法都可以实现需求,其中方法一最为简洁,适合大多数场景;方法三更适合处理百万级以上的大数据表。
内容的提问来源于stack exchange,提问作者Ian Wang
相关产品推荐
相关产品推荐

