gpt4 book ai didi

R:如何使 data.table 只读而不复制它(例如用于数据验证)

转载 作者:行者123 更新时间:2023-12-02 13:20:33 24 4
gpt4 key购买 nike

我进行数据整理 (ETL) 以将新数据加载到数据库中,并希望让用户基于包含准备好的数据的现有 data.table 对象实现自己的数据验证功能。

如何避免用户在验证函数中(有意或无意)更改(修改)我的 data.table 的数据而不进行复制(因为它会减慢验证处理速度)以及整个 ETL 过程)?

仅在验证功能中暂时需要锁定/写保护数据...

简化示例:

library(data.table)

DT <- as.data.table(mtcars)
DT[, row.number := 1:(.N)] # add a row number column to allow identification of invalid rows
DT[c(3,6,7), cyl := 100] # create some data errors (100 cylinders in the car)

# correctly implemented validate function (does not change the data)
validate <- function(data) {
data[cyl > 10, .(row.number = row.number, col.name = "cyl", col.value = cyl,
severity = "ERROR", msg = "More than 10 cylinders")]
}

validate(DT)

输出正常,传递给 validate() 函数的 data.table 未更改:

   row.number col.name col.value severity                    msg
1: 3 cyl 100 ERROR More than 10 cylinders
2: 6 cyl 100 ERROR More than 10 cylinders
3: 7 cyl 100 ERROR More than 10 cylinders

我想避免的是用户像这样实现 validate() 并修改原始数据:

validate.with.side.effects <- function(data) {
data[, max.cyl := 10] # this adds a new column into the original data.table!
data[cyl > max.cyl, .(row.number = row.number, col.name = "cyl", col.value = cyl, severity = "ERROR", msg = "More than 10 cylinders")]
}

此实现将修改DT中的原始data.table!

更新:

有一个开放的功能请求: https://github.com/Rdatatable/data.table/issues/1086

功能请求基于不同上下文中的类似要求(包中的不可变数据):Lock or protect a data.table in R

更新2

还有另一个类似的功能请求: https://github.com/Rdatatable/data.table/issues/778

还有另一个类似的问题: How does one return a 'const' data.table from an R function?

更新3:可以使用不可变的data.frame吗?

通常是的(使 data.frame 只读),但此解决方案不满足问题的要求:

library(plyr)
idf <- idata.frame(DT)
idf[, max.cly := 10]
# Error in `:=`(max.cly, 10) :
# Check that is.data.table(DT) == TRUE. Otherwise, := and `:=`(...) are defined for use in j, once only and in particular ways. See help(":=").

validate(idf)
# Error in `[.idf`(data, cyl > 10, .(row.number = row.number, col.name = "cyl", :
# object 'cyl' not found

# it is no longer a data.table...
class(idata.frame(DT))
# [1] "idf" "environment"

# so that the data.table syntax does NOT work anymore...
idf[cyl > 10, .(row.number = row.number, col.name = "cyl", col.value = cyl,
severity = "ERROR", msg = "More than 10 cylinders")]
# Error in `[.idf`(idf, cyl > 10, .(row.number = row.number, col.name = "cyl", :
# object 'cyl' not found

最佳答案

immutable data frame允许你完成你需要的事情吗?

R 的对象通常是不可变的,并采用使用时复制语义来应用函数(有关更多详细信息,请参阅 this link)。 data.table 有点奇怪,因为它允许与对象直接交互,绕过使用时复制,这使得它更像是一个可变对象。您所描述的场景需要一个具有可变和不可变属性的对象。您可能必须复制 dt 才能应用验证而不修改原始对象。

关于R:如何使 data.table 只读而不复制它(例如用于数据验证),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44995065/

24 4 0