在data.table中用均值替换字符串数值范围的优化方案求助
解决字符串数值范围替换为均值的问题(data.table环境下)
错误原因分析
在data.table的j参数中,..是特殊语法,用于引用父环境中的变量,因此你之前用..1、..3会被data.table误认为要寻找名为1、3的变量,而非gsubfn的捕获组参数,这就导致了报错。
解决方案
方案1:修改gsubfn的匿名函数写法(规避..冲突)
直接给捕获组定义参数名,代替..n的写法,避开和data.table的语法冲突:
library(data.table) library(gsubfn) DT <- data.table(raw.data = c("1-2 min", "3-5 min or 2-4 min"), desirable.data = c("1.5 min", "4 min or 3 min")) DT[, new := gsubfn(pattern = "(\\d+)-(\\d+)", function(a, b) { avg <- mean(c(as.numeric(a), as.numeric(b))) # 处理整数均值,避免显示4.0这类冗余格式 if (avg %% 1 == 0) as.character(as.integer(avg)) else as.character(avg) }, x = raw.data)]
方案2:使用stringr的str_replace_all(支持函数型替换)
str_replace_all支持传递函数作为替换逻辑,无需依赖gsubfn,同样可以实现动态计算均值:
library(data.table) library(stringr) DT <- data.table(raw.data = c("1-2 min", "3-5 min or 2-4 min"), desirable.data = c("1.5 min", "4 min or 3 min")) DT[, new := str_replace_all(raw.data, "(\\d+)-(\\d+)", function(match) { # 提取捕获到的两个数值 num1 <- as.numeric(match[2]) num2 <- as.numeric(match[3]) avg <- mean(c(num1, num2)) # 格式化输出,整数显示为整数,非整数保留小数 as.character(ifelse(avg %% 1 == 0, as.integer(avg), avg)) })]
验证结果
执行上述代码后,DT$new会和desirable.data完全一致:
> DT raw.data desirable.data new 1: 1-2 min 1.5 min 1.5 min 2: 3-5 min or 2-4 min 4 min or 3 min 4 min or 3 min
内容的提问来源于stack exchange,提问作者Ian Wang
相关产品推荐
相关产品推荐

