R语言data.table中用lapply+正则批量创建列报错,求解决方法
解决data.table批量提取指定字符串后数值生成新列的报错问题
问题背景
需求:从data.table的某列中提取指定字符串后的数值,批量生成新列。
示例代码:
dt <- data.table(col.1 = c("a1, b2, c3, d4")) x <- c("a", "b", "c") dt[, (x) := lapply(FUN = str_match(string = .SD, pattern = paste0("(?<=", x, ")([\\d])"))[, 2], X = x), .SDcols = "col.1"]
期望结果:
desirable <- data.table(col.1 = c("a1, b2, c3, d4"), a = c("1"), b = c("2"), c = c("3"))
实际运行报错:
Error in match.fun(FUN) :
c("'str_match(string = .SD, pattern = paste0("(?<=", x, ")([\\d])"))[, ' is not a function, character or symbol", "' 2]' is not a function, character or symbol")
错误原因
lapply的FUN参数必须传入函数对象,你直接传入了str_match(...)[,2]这个计算表达式,R无法将其识别为合法函数,因此触发报错。.SD是data.table的子数据集(此处为单列数据框),str_match处理数据框返回矩阵,直接索引[,2]的逻辑不符合lapply对每个元素迭代的要求。
修正方案
方法一:规范lapply用法,包装提取逻辑为函数
library(data.table) library(stringr) dt <- data.table(col.1 = c("a1, b2, c3, d4")) x <- c("a", "b", "c") dt[, (x) := lapply(x, function(prefix) { # 为每个前缀生成匹配正则 pattern <- paste0("(?<=", prefix, ")(\\d)") # 提取对应数值,取匹配结果的第二列(捕获组内容) str_match(col.1, pattern)[, 2] })]
方法二:用str_extract简化提取逻辑
如果只需要匹配前缀后的第一个数字,str_extract更简洁:
dt[, (x) := lapply(x, function(prefix) { str_extract(col.1, paste0("(?<=", prefix, ")\\d")) })]
运行后输出符合预期:
> dt col.1 a b c 1: a1, b2, c3, d4 1 2 3
内容的提问来源于stack exchange,提问作者Ian Wang
相关产品推荐
相关产品推荐

