gpt4 book ai didi

r - 如何正确地将 `dput` 拟合线性模型(通过 `lm` )转换为 ASCII 文件并稍后重新创建?

转载 作者:行者123 更新时间:2023-12-04 10:06:54 26 4
gpt4 key购买 nike

我要坚持一个lm对象到文件并将其重新加载到另一个程序中。我知道我可以通过 saveRDS 写入/读取二进制文件来做到这一点。/readRDS ,但我想要一个 ASCII 文件而不是二进制文件。在更一般的层面上,我想知道为什么我的习语在 dput 中阅读。输出一般不会像我期望的那样表现。

以下是简单拟合的示例,以及模型的成功和失败再创建:

dat_train <- data.frame(x=1:4, z=c(1, 2.1, 2.9, 4))
fit <- lm(z ~ x, dat_train)
rm(dat_train) # Just to make sure fit is not dependent upon `dat_train existence`

dat_score <- data.frame(x=c(1.5, 3.5))

## This works (of course)
predict(fit, dat_score)
# 1 2
# 1.52 3.48

保存到二进制文件的工作原理:
## http://stackoverflow.com/questions/5118074/reusing-a-model-built-in-r
saveRDS(fit, "model.RDS")
fit2 <- readRDS("model.RDS")
predict(fit2, dat_score)
# 1 2
# 1.52 3.48

这也是如此( dput 它在 R session 中不是文件):
fit2 <- eval(dput(fit))
predict(fit2, dat_score)
# 1 2
# 1.52 3.48

但是如果我将文件持久化到磁盘,我无法弄清楚如何恢复正常形状:
dput(fit, file = "model.R")
fit3 <- source("model.R")$value

# Error in is.data.frame(data): object 'dat_train' not found

predict(fit3, dat_score)
# Error in predict(fit3, dat_score): object 'fit3' not found

试图明确地使用 eval也不起作用:
## http://stackoverflow.com/questions/9068397/import-text-file-as-single-character-string
dput(fit, file="model.R")
fit4 <- eval(parse(text=paste(readLines("model.R"), collapse=" ")))

# Error in is.data.frame(data): object 'dat_train' not found

predict(fit4, dat_score)
# Error in predict(fit4, dat_score): object 'fit4' not found

在上述两种情况下,我预计 fit3fit4两者都可以工作,但它们不会重新编译成 lm我可以使用的对象 predict() .

任何人都可以告诉我如何将模型持久化到带有 structure(...) 的文件中类似 ASCII 的结构,然后将其重新读取为 lm我可以在 predict() 中使用的对象?为什么我目前的方法不起作用?

最佳答案

第一步:

您需要控制解析选项:

dput(fit, control = c("quoteExpressions", "showAttributes"), file = "model.R") 

您可以在 ?.deparseOpts 中阅读有关所有可能选项的更多信息.

"quoteExpressions"用 quote 包装所有调用/表达式/语言,以便在您稍后重新解析它们时不会评估它们。笔记:
  • source正在做解析;
  • call适合的“lm”对象中的字段是一个调用:
    fit$call
    # lm(formula = z ~ x, data = dat_train)

  • 因此,如果没有“quoteExpressions”,R 将尝试评估 lm解析时调用。如果我们对它进行评估,它正在拟合一个线性模型,而 R 的目标是找到 dat_train ,它将不存在于您的新 R session 中。

    “showAttributes”是另一个强制性选项,因为“lm”对象具有类属性。您当然不想丢弃所有类属性而只导出一个普通的“列表”对象,对吗?此外,“lm”对象中的许多元素,例如 model (模型架), qr (紧凑的 QR 矩阵)和 terms (terms info) 等都有属性。你想把它们都保留下来。

    如果不设置 control ,默认设置为:
    control = c("keepNA", "keepInteger", "showAttributes")

    将会被使用。如您所见,没有“quoteExpressions”,因此您会遇到麻烦。

    您还可以指定“keepInteger”和“keepNA”,但我认为不需要“lm”对象。

    ------

    第 2 步:

    上一步会得到 source工作正常。您可以恢复模型:
    fit1 <- source("model.R")$value

    然而,它还没有为像 summary 这样的通用函数做好准备。和 predict上类。为什么?

    关键问题是 terms对象在 fit1不是真正的“术语”对象,而只是一个公式(它甚至不是一个公式,而只是一个没有“公式”类的“语言”对象!)。比较一下 fit$termsfit1$terms ,你会看到不同之处。不要惊讶;我们之前已经设置了“quoteExpressions”。虽然这绝对有助于防止评估 call ,它对 terms 有副作用.所以我们需要重构 terms尽我们所能。

    幸运的是,这样做就足够了:
    fit1$terms <- terms.formula(fit1$terms)

    尽管这仍然无法恢复 fit$terms 中的所有信息(就像缺少变量类一样),它很容易成为有效的“术语”对象。

    为什么“条款”对象很重要?因为所有的泛型函数都依赖于它。您可能不需要了解更多信息,因为它确实是技术性的,所以我就到此为止。

    一旦完成,我们就可以成功使用 predict (还有 summary ):
    predict(fit1)  ## no `newdata` given, using model frame `fit1$model`
    # 1 2 3 4
    #1.03 2.01 2.99 3.97

    predict(fit1, dat_score) ## with `newdata`
    # 1 2
    #1.52 3.48

    -------

    结语:

    尽管我已经向您展示了如何让事情发挥作用,但我真的不建议您在一般情况下这样做。当您将模型拟合到大型数据集时,“lm”对象将非常大,例如, residuals , fitted.values是长向量,而 qrmodel是巨大的矩阵/数据框。所以想想这个。

    关于r - 如何正确地将 `dput` 拟合线性模型(通过 `lm` )转换为 ASCII 文件并稍后重新创建?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41645120/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com