如何用data.table通用拆分任意字符串列为多列?
通用化data.table字符串拆分方案
你的代码错误原因很明确:循环里用.()包裹indN时,传递的是列名字符串本身(比如"typeA"),而不是引用dtToSplit中对应的列,所以拆分结果全是列名的重复值。
方案一:修正循环写法
用get()函数根据列名字符串获取对应列,或者通过.SD[[indN]]引用列,两种写法都能解决问题:
写法1:使用get()
dtToSplit = data.table(attr = c(1,30,4,6), typeA=c('foo_and_bar','foo_and_bar_2'), typeB=c('cat_and_dog', 'orange_and_apple')) namesSpl <- c('typeA', 'typeB') for (indN in namesSpl) { dtToSplit[, paste0(indN, 1:2) := tstrsplit(get(indN), "_and_")] }
写法2:使用.SD[[indN]]
for (indN in namesSpl) { dtToSplit[, paste0(indN, 1:2) := tstrsplit(.SD[[indN]], "_and_"), .SDcols = indN] }
方案二:无循环的批量处理(更符合data.table风格)
data.table原生支持批量列操作,不需要循环就能完成通用拆分,效率更高:
dtToSplit = data.table(attr = c(1,30,4,6), typeA=c('foo_and_bar','foo_and_bar_2'), typeB=c('cat_and_dog', 'orange_and_apple')) namesSpl <- c('typeA', 'typeB') # 生成所有新列名 new_cols <- unlist(lapply(namesSpl, function(x) paste0(x, 1:2))) # 批量拆分并赋值 dtToSplit[, (new_cols) := lapply(.SD, tstrsplit, split = "_and_"), .SDcols = namesSpl]
正确结果
执行后得到的正确数据表如下:
attr typeA typeB typeA1 typeA2 typeB1 typeB2 1: 1 foo_and_bar cat_and_dog foo bar cat dog 2: 30 foo_and_bar_2 orange_and_apple foo bar_2 orange apple 3: 4 foo_and_bar cat_and_dog foo bar cat dog 4: 6 foo_and_bar_2 orange_and_apple foo bar_2 orange apple
内容的提问来源于stack exchange,提问作者Lorenzo Tattini
相关产品推荐
相关产品推荐

