R语言data.table如何将3个count列melt为单列匹配对应dur值
data.table按行匹配对应列值的简洁实现
你当前的场景不需要做全量melt后再过滤,直接用data.table原生的逐行索引写法效率最高,代码也最简洁。
方法1:逐行动态取列(推荐,性能最优)
核心逻辑是逐行读取当前dur字段的值,拼接.count后缀后直接定位到对应列的取值,没有冗余的长宽表转换操作:
library(data.table) # 构造示例数据 dt <- data.table(age = rep(c("5-16", "17-39"), each = 3), dur = rep(c("short","medium","long"), 2), short.count = rep(c(23,45),each = 3), medium.count = rep(c(12,34), each = 3), long.count = rep(c(3,5), each = 3)) # 一行代码得到目标结果 dt_res <- dt[, .(age, dur, count = .SD[[paste0(dur, ".count")]]), by = .I][, .I := NULL]
运行后输出结果完全匹配预期:
age dur count 1: 5-16 short 23 2: 5-16 medium 12 3: 5-16 long 3 4: 17-39 short 45 5: 17-39 medium 34 6: 17-39 long 5
说明:这里用by = .I是data.table内置的按行分组语法,比写by=1:nrow(dt)更规范,最后删掉自动生成的.I行号列即可。
方法2:melt后过滤(常规长宽表转换思路)
如果更习惯用melt语法,也可以先把宽表转成长表,再匹配dur和count类型保留对应行:
dt_res2 <- melt( dt, id.vars = c("age", "dur"), measure.vars = patterns("\\.count$"), variable.name = "count_type", value.name = "count" )[, count_type := gsub("\\.count", "", count_type)][count_type == dur, .(age, dur, count)]
这种写法逻辑直观,但会先生成3倍行数的中间长表再做过滤,数据量较大时性能弱于第一种方法。
内容的提问来源于stack exchange,提问作者matto
相关产品推荐
相关产品推荐

