这是我的相关问题的继续:Error when trying to interactively load data file saved by paused batch script。我决定分别用一个可重复的例子来表达我的问题,以避免使前一个问题中已经很大的描述更大。在以下可重现的示例中,我希望检索存储对象的值(“重要数据”),但是,如您所见,我检索对象本身的名称(“sf.data.devLinks”)。我怀疑它可能是因为我使用as.name
,但我在交互式会话中另外测试了一个原始示例,as.name
工作正常。如您所见,我也尝试过使用eval
和substitute
,但它没有帮助。
library(RCurl)
info <- "Important data"
ATTR <- "SQL"
request <- "SELECT info FROM topSecret"
dataName <- "sf.data.devLinks"
rdataFile <- "/tmp/testAttr.rds"
save <- TRUE
getData <- function() {
return (info)
}
requestDigest <- base64(request)
# check if the archive file has already been processed
message("\nProcessing request \"", request, "\" ...\n")
# read back the object with the attribute
if (file.exists(rdataFile)) {
# now check if request's SQL query hasn't been modified
data <- readRDS(rdataFile)
message("Retrieved object '", data, "', containing:\n")
message(str(data))
requestAttrib <- attr(data, ATTR, exact = TRUE)
if (is.null(requestAttrib)) {
message("Object '", data, "' doesn't have attribute \"",
ATTR, "\"\n")
}
else {
message("Object '", data, "' contains attribute ", ATTR, ":\n\"",
base64(requestAttrib), "\"\n")
if (identical(requestDigest, requestAttrib)) {
message("Processing skipped: RDS file is up-to-date.\n")
save <- FALSE
return
}
}
rm(data)
}
if (save) {
message("Saving results of request \"",
request, "\" as R data object ...\n")
assign(dataName, getData())
data <- as.name(dataName)
#eval(substitute(assign(dataName, getData()),
# list(data <- as.name(dataName))))
# save hash of the request's SQL query as data object's attribute,
# so that we can detect when configuration contains modified query
attr(data, ATTR) <- base64(request)
# save current data frame to RDS file
saveRDS(data, rdataFile)
}
请注意,测试此代码需要运行两次(首次运行 - 存储对象,第二次 - 检索)。
答案 0 :(得分:1)
问题在于您使用as.name
,而不是在保存对象的代码中。这完全没问题:
data <- 1:10
object.name <- 'data.name'
query <- 'SELECT * FROM TABLE'
file <- tempfile()
assign(object.name, structure(data, SQL = query))
saveRDS(get(object.name), file)
read.object <- readRDS(file)
identical(read.object, get(object.name))
您正在创建名称对象,并为其指定属性,但您希望数据存在。它不会是,symbol
只是指向值的指针。您需要使用eval()或类似的东西来获取symbol
。
答案 1 :(得分:0)
最后,我能够回到这个问题。我找到了正确的解决方案,所以我回答了自己的问题。这里的答案基于我的可重现的示例,但我在更复杂的现实世界R代码中做了相应的更改。 解决方案相当简单,但双重,如下所示。
将原始代码data <- readRDS(rdataFile)
替换为assign(dataName, readRDS(rdataFile))
。
将原始代码as.name(dataName)
替换为get(dataName)
。这里get()
的替代方法是eval(parse(text=dataName))
,恕我直言更麻烦。
下面我根据原始可重现的示例提供解决方案的完整源代码。我没有提供脚本的输出,这很容易重现(记得至少运行两次脚本)。再次感谢所有帮助解决这个问题的人。
library(RCurl)
info <- "Important data"
ATTR <- "SQL"
request <- "SELECT info FROM topSecret"
dataName <- "sf.data.devLinks"
rdataFile <- "/tmp/testAttr.rds"
save <- TRUE
getData <- function() {
return (info)
}
requestDigest <- base64(request)
# check if the archive file has already been processed
message("\nProcessing request \"", request, "\" ...\n")
# read back the object with the attribute
if (file.exists(rdataFile)) {
# now check if request's SQL query hasn't been modified
assign(dataName, readRDS(rdataFile))
message("Retrieved object '", dataName, "', containing:\n")
message(str(get(dataName)))
requestAttrib <- attr(get(dataName), ATTR, exact = TRUE)
if (is.null(requestAttrib)) {
message("Object '", dataName, "' doesn't have attribute \"",
ATTR, "\"\n")
}
else {
message("Object '", dataName, "' contains attribute \"",
ATTR, "\":\n\"", base64(requestAttrib), "\"\n")
if (identical(requestDigest, requestAttrib)) {
message("Processing skipped: RDS file is up-to-date.\n")
save <- FALSE
return
}
}
}
if (save) {
message("Saving results of request \"",
request, "\" as R data object ...\n")
assign(dataName, getData())
message(str(dataName))
data <- get(dataName)
# alternative to using get(), but more cumbersome:
# data <- eval(parse(text=dataName))
# save hash of the request's SQL query as data object's attribute,
# so that we can detect when configuration contains modified query
attr(data, ATTR) <- base64(request)
message(str(data))
# save current data frame to RDS file
saveRDS(data, rdataFile)
}