r - 避免覆盖 data.table 函数中的现有列
问题描述
我正在编写一个以 data.table 作为参数的函数。data.table 的列名部分指定为参数,但并非所有列名都指定,所有原始列都需要维护。在函数内部,需要将一些列添加到 data.table 中。即使在函数内部复制了 data.table,我也想以一种保证不会覆盖现有列的方式添加这些列。鉴于列名未知,确保我不会覆盖列的最佳方法是什么?
这是一种方法:
#x is a data.table and knownvar is a column name of that data.table
f <- function(x,knownvar){
x <- copy(x)
tempcol <- "z"
while(tempcol %in% names(x))
tempcol <- paste0("i.",tempcol)
tempcol2 <- "q"
while(tempcol2 %in% names(x))
tempcol2 <- paste0("i.",tempcol2)
x[, (tempcol):=3]
eval(parse(text=paste0("x[,(tempcol2):=",tempcol,"+4]")))
x
}
请注意,即使我在这里复制 x,我仍然需要这个过程来提高内存效率。有没有更简单的方法来做到这一点?可能不使用eval(parse(text=
?
显然我可以在函数环境中创建一个局部变量(例如向量)(而不是将其显式添加为 data.table 的列),但如果我需要排序/加入 data.table 这将不起作用. 另外,我可能想显式返回一个包含原始变量和新列的 data.table。
解决方案
set
这是使用和非标准评估来编写函数的一种方法substitute() + eval()
。
注 1:如果新列是基于 中的列名newcols
(而不是 中的列名knownvar
)创建的,则中的字符名将newcols
转换为带有as.name()
(或等效as.symbol()
)的符号。
注2:新列newvals
只能以合理的顺序添加,即如果列q
需要列z
,列z
应在列之前添加q
。
library(data.table)
f <- function(x, knownvar) {
## remove if x should be modified in-place
x <- copy(x)
## new column names
newcols <- setdiff(make.unique(c(names(x), c("z", "q"))), names(x))
## new column values based on knownvar or new column names
zcol <- as.name(newcols[1])
newvals <- list(substitute(3 * knownvar), substitute(zcol + 4))
for(i in seq_along(newvals)) {
set(x, j = newcols[i], value = eval(newvals[[i]], envir = x))
}
return(x)
}
## example data
x <- as.data.table(mtcars)
x[, c("q", "q.1") := .(mpg, 2 * mpg)]
head(f(x, mpg))
#> mpg cyl disp hp drat wt qsec vs am gear carb q q.1 z q.2
#> 1: 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 21.0 42.0 63.0 67.0
#> 2: 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 21.0 42.0 63.0 67.0
#> 3: 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 22.8 45.6 68.4 72.4
#> 4: 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 21.4 42.8 64.2 68.2
#> 5: 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 18.7 37.4 56.1 60.1
#> 6: 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1 18.1 36.2 54.3 58.3
推荐阅读
- typescript - 获取 Firebase 云函数快照子数据
- json - Swift:解析不知道键值的 JSON 文件
- javascript - 使用 React 集成 Spreadshop 站点
- html - 无法移动徽标
- javascript - Discord.js 获取频道中所有消息的数组
- c - 在 c 中动态分配内存时,我应该同时使用 if 和 else 条件吗?
- r - 如何在modelsummary包的msummary中的系数名称中使用数学符号/乳胶数学?
- windows - Spark 历史服务器设置
- asp.net - 如何在运行 ASP.NET Core 的 Docker 容器中使用 webpack 进行本地开发并在 Azure 上托管时设置 https
- javascript - 无法获得长寿令牌 instagram