如何在data.table中用lapply为动态列设置指定最小值?
动态为data.table多列设置各自的最小值
问题场景
有一个列数动态可变的data.table,需要为匹配col<数字>格式的每一列设置对应的指定最小值。示例数据如下:
library(data.table) dt <- data.table( urn = 1:10, col1 = 5:14, col2 = 11:20 )
错误原因分析
你之前的两种方法都错误地将列名字符向量my_cols当作列的实际数值进行处理,导致逻辑错误或报错:
- 第一种方法中,
my_cols < x是字符串与数字的比较,结果全为FALSE,最终所有行被赋值为x; - 第二种方法同理,用列名字符串参与数值比较,直接触发类型不匹配的错误。
正确解决方案
利用Map(或mapply)将目标列与对应最小值一一配对,结合pmax函数实现“取列值与最小值中的较大者”,即可完成动态替换:
方法1:使用Map与.SD
min_vals <- c(10, 15) my_cols <- grep("^col", colnames(dt), value = TRUE) # 对每个目标列应用pmax,替换低于最小值的行 dt[, (my_cols) := Map(function(col, min_val) pmax(.SD[[col]], min_val), my_cols, min_vals)]
方法2:使用mapply与.SDcols(更简洁)
dt[, (my_cols) := mapply(function(col_val, min_val) pmax(col_val, min_val), .SD, min_vals, SIMPLIFY = FALSE), .SDcols = my_cols]
更安全的命名向量版本(避免顺序错误)
如果担心min_vals的顺序与列顺序不匹配,可以将min_vals定义为命名向量,确保每个列对应正确的最小值:
min_vals <- c(col1 = 10, col2 = 15) my_cols <- grep("^col", colnames(dt), value = TRUE) dt[, (my_cols) := Map(function(col, min_val) pmax(.SD[[col]], min_val), my_cols, min_vals[my_cols])]
验证结果
执行后得到期望输出:
dt # urn col1 col2 # <int> <int> <int> # 1: 1 10 15 # 2: 2 10 15 # 3: 3 10 15 # 4: 4 10 15 # 5: 5 10 15 # 6: 6 10 16 # 7: 7 11 17 # 8: 8 12 18 # 9: 9 13 19 # 10: 10 14 20
内容的提问来源于stack exchange,提问作者Dan
相关产品推荐
相关产品推荐

