R语言data.table函数列引用报错:SAP文档字段生成问题
问题场景与报错说明
在SAP业务场景中,需生成包含Document No(文档编号)和Position(行项目)的交易文本文件,要求同一UniqueID对应相同文档编号及连续行项目。
原测试代码(非函数形式)运行正常,但封装为函数后触发错误:
Error in setorderv(x, cols, order, na.last) : some columns are not in the data.table: IdFld
原可运行测试代码
library(data.table) # 示例数据 tblSAP <- data.table( UniqueID = c(200,200,300,300,400,400) ) # 生成Document No和Position字段 tblSAP <- setorder(tblSAP, cols=UniqueID) dfUniqueID <- tblSAP[,.(UniqueID)] DT1 <- dfUniqueID[,.N, by=.(UniqueID, "Document No"=rleid(UniqueID))] DT2 <- dfUniqueID[,seq_len(.N), by = UniqueID] |> setnames(old = "V1",new = "Position") DT3 <- DT1[DT2,on = .(UniqueID)][,-c("N")] tblSAP <- cbind(tblSAP,DT3[,-c("UniqueID")])
报错的函数代码
SAPDocPos <- function(tblSAP,IdFld){ tblSAP <- setorder(tblSAP,cols=IdFld) dfUniqueID <- tblSAP[,.(IdFld)] DT1 <- dfUniqueID[,.N, by=.(IdFld, "Document No"=rleid(IdFld))] DT2 <- dfUniqueID[,seq_len(.N), by = IdFld] %>% setnames(old = "V1",new = "Position") DT3 <- DT1[DT2,on = .(IdFld)][,-c("N")] tblSAP <- cbind(tblSAP,DT3[,-c("UniqueID")]) return(tblSAP) } SAPDocPos(tblSAP,UniqueID)
错误原因
函数中直接使用IdFld作为列名引用时,data.table会将其视为字面量字符串"IdFld",而非传入的实际列名(如UniqueID),导致找不到对应列。此外,最后一步硬编码删除UniqueID列,无法适配不同的传入字段名。
修复后的函数代码
library(data.table) SAPDocPos <- function(tblSAP, IdFld){ # 使用整洁评估{{}}引用传入的列名 tblSAP <- setorder(tblSAP, cols = {{IdFld}}) # 创建包含目标字段的临时表 dfUniqueID <- tblSAP[, .({{IdFld}})] # 生成Document No(基于rleid分组) DT1 <- dfUniqueID[, .N, by = .({{IdFld}}, "Document No" = rleid({{IdFld}}))] # 生成连续的Position行项目 DT2 <- dfUniqueID[, seq_len(.N), by = {{IdFld}}] |> setnames(old = "V1", new = "Position") # 关联表并删除冗余列 DT3 <- DT1[DT2, on = .({{IdFld}})][, -c("N")] # 合并回原表,删除重复的目标字段列 tblSAP <- cbind(tblSAP, DT3[, -c(as.character(substitute(IdFld)))]) return(tblSAP) } # 调用示例 tblSAP <- data.table(UniqueID = c(200,200,300,300,400,400)) result <- SAPDocPos(tblSAP, UniqueID) print(result)
关键修改点
- 使用
{{IdFld}}(整洁评估语法)在data.table中正确引用传入的列名,避免将参数名视为字面量列名 - 最后一步删除重复列时,通过
substitute(IdFld)动态获取传入的字段名,替代硬编码的UniqueID - 统一使用
|>管道符(保持与原代码风格一致,若需保留%>%需提前加载dplyr)
内容的提问来源于stack exchange,提问作者Mohammed Barakat
相关产品推荐
相关产品推荐

