【问题标题】:R: How far does it go? (Plus venting)R:能走多远? (加上通风)
【发布时间】:2016-07-30 13:18:16
【问题描述】:

我有一个名为defaultPacks 的对象,其中包含我使用的所有计算机上安装的软件包的名称。很多缩写:

defaultPacks <- c(
  "AER",
  "plyr",
  "dplyr" 
) 

我想将此对象保存到所有文件都可以访问的共享目录中。我为此使用 Dropbox,当 R 运行时,同步总是暂停。

save(defaultPacks, 
file.path("C:","Users","andrewH","Dropbox","R_PROJ","sharedSettings.rdata")) 

然后我想加载对象并安装名称在对象defaultPacks 中的包。

SyncPacks <- function(fileString){
  defaultPacks <- load(file=fileString)
  install.packages(defaultPacks, repos="http://cran.us.r-project.org")
}
SyncPacks(file.path("C:","Users","andrewH","Dropbox","R_PROJ","sharedSettings.rdata")

如果我这样做,我会收到警告:

Warning in install.packages: package ‘defaultPacks’ is not available (for R version 3.2.1)

我在加载和分配defaultPacks 后立即查看它:字符串"defaultPacks"。所以它似乎加载只是一个字符串而不是一个对象。

所以我回到我的存档,然后尝试

save(get(defaultPacks), file.path(etc.))

这给了我一个不同的错误:

Error in save(get("defaultPacks"), file = file.path("C:", "Users", "andrewH",  : 
  object ‘get("defaultPacks")’ not found.

然后我尝试dynGet(),结果相同。

所以之前它把一个符号当作一个字符串,现在它把一个函数当作一个字符串。

所以我尝试使用列表选项进行保存:

save(list = defaultPacks, file = file.path(etc))

又得到一个错误:

Error in save(list = defaultPacks, file = file.path("C:", "Users", "andrewH",  : 
  objects ‘AER’, ‘plyr’, ‘dplyr’, (etc.) not found

所以在我无法我的字符向量之前,现在我正在正确过去它,评估defaultPacks以找到字符串,然后处理每个字符串作为一个符号,并将其评估为它的(不存在的)对象。

所以,我想知道如何进行这项工作。但我要求的远不止这些。我一直有这个问题,或者类似的问题。在使用 R 几年后,我仍然每周使用几次。我不知道在任何给定情况下 R 将采取多少评估步骤。我给一个函数一个对象名称,该函数将其视为一个字符串。我将一个字符串交给一个函数,然后 R 函数将其转换为一个符号并尝试对其进行评估。在这里,我不明白为什么save函数不保存我给它的对象,然后用load还给它。

我已经阅读了十本不同的 R 书籍中关于范围界定的讨论,从 Chambers 的“数据分析软件”到 Wickham 的“Advanced R”。两次。在某些情况下四次。我知道一个函数的四种环境,以及调用栈和环境父链的区别。然而,很明显我缺少一些基本的东西。不仅仅是我不知道为什么save 没有在其... 参数中取名字并将其保存为对象(除非问题出在加载端)。我不知道我是怎么知道的。函数描述说,在...s 中,“要保存的对象的名称(作为符号或字符串)。”那么为什么要将名称保存为字符串呢?或者为什么 load 返回一个字符串,如果 save 保存了一个对象?我怎么能预测到呢?

经验丰富的 R 程序员,我知道您可以提前知道给定的 R 函数将如何处理其参数之一。你知道它将被评估多远。你可以让它去你想去的地方,然后停止。每次你想弄清楚它认为它的参数意味着什么时,你不必将str()'s 写到你的函数中。你是怎么做到的?

血腥的“R 地狱”。这是一个轻描淡写的说法。

【问题讨论】:

  • 只需使用 load(file=fileString)。不必将其分配回 defaultPacks
  • Load 返回“创建的对象名称的字符向量,不可见。”所以在这种情况下,它返回一个字符串“defaultPacks”
  • @chinsoon12 感谢您澄清这一点。在任何情况下,返回值都不是 OP 所期望的;并且通过将此返回值分配给defaultPacks,该命令变得无用,因为它重新定义了刚刚加载的变量。
  • @RHertel,你想解决他的第二个问题吗? ;)
  • 正如@chinsoon12 正确指出defaultPacks &lt;- load(file=fileString) 是错误的,您只需要load(file=fileString),因为load 函数会自动将存储的变量重新创建到环境中

标签: r scope functional-programming symbols evaluation


【解决方案1】:

查看问题的一种方法是注意defaultPacks 的值在这些操作之前到之后的变化。

> fname = tempfile()
> orig = defaultPacks = c("AER", "plyr", "dplyr")
> save(defaultPacks, file=fname)
> defaultPacks = load(fname)
> identical(orig, defaultPacks)
[1] FALSE

问题从了解save() 的作用开始。从?save 开始,保存的对象名为defaultPacks,其值为c("AER", "plyr", "dplyr")save() 可以保存多个对象,每个对象都有一个名称和关联的值,因此它必须以某种方式保存每个对象的名称。

load() 恢复save() 写入的对象,并返回(从?load)“创建的对象名称的字符向量”。在这种情况下,load() 恢复(在全局环境中创建)符号 defaultPacks,用默认包的字符向量填充它,并返回对象的名称(即长度为 1“defaultPacks”的字符向量)( s) 它已经恢复。然后返回值覆盖恢复的值,我们有defaultPacks = "defaultPacks"

install.packages 的第一个参数并没有做任何花哨的事情,它来自?install.packages 是“应下载当前版本的包名称的字符向量”。字符向量恰好是符号defaultPacks,但是错误来自符号的值,即字符向量"defaultPacks"

save()load() 或多或少必须按照它们支持多个对象的方式工作。另一方面,saveRDS()readRDS()(好吧,为什么 read 而不是 load?)有一个保存单个对象的协定。无需存储已保存对象的名称即可恢复与其关联的值。所以saveRDS(defaultPacks, fname); defaultPacks = readRDS(fname)有效,特别是这一系列操作前后defaultPacks的值保持不变。

> orig = defaultPacks = c("AER", "plyr", "dplyr")
> saveRDS(defaultPacks, fname)
> defaultPacks = readRDS(fname)
> identical(orig, defaultPacks)
[1] TRUE

没有太多混蛋的意思,回答“有经验的 R 程序员......你是怎么做的?”这个问题的答案。上面的? 暗示了答案——通过仔细阅读手册。此外,在基本 R 代码中,评估是非标准的地方并不多——公式和library 是罪魁祸首——因此认识到问题是什么不是可以帮助专注于实际发生了什么。

【讨论】:

    猜你喜欢
    • 2011-01-20
    • 2023-03-11
    • 2010-09-05
    • 2019-12-13
    • 2013-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多