R:它能走多远? (加上通风)

标签 r scope functional-programming symbols evaluation

我有一个名为 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 的“高级 R”。两次。在某些情况下四次。我知道一个函数的四个环境,以及调用栈和环境父链的区别。然而,很明显我缺少一些基本的东西。这不仅仅是因为我不知道为什么 save 没有在其 ... 参数中取一个名字并将其保存为一个对象(除非问题出在加载端)。我不知道我怎么可能知道。函数描述说,对于 ...,“要保存的对象的名称(作为符号或字符串)”。那么为什么将名称保存为字符串呢?或者如果 save 保存了一个对象,为什么 load 返回一个字符串?我怎么能预测呢?

有经验的 R 程序员,我知道你可以提前告诉给定的 R 函数将如何处理它的参数之一。你知道它会被评估到什么程度。你可以让它走多远,然后停下来。每次您想弄清楚它认为其参数到底是什么意思时,您不必每次都将 str() 写入您的函数中。你是怎么做到的?

该死的“R hell ”。这是一个轻描淡写的说法。

最佳答案

查看问题的一种方法是注意 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”)的向量。然后返回值覆盖恢复的值,我们有 defaultPacks = "defaultPacks"

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

save()load() 或多或少必须以它们支持多个对象的方式工作。另一方面,saveRDS()readRDS()(好吧,为什么是 read 而不是 load?)保存单个对象的契约(Contract)。不需要存储已保存对象的名称即可恢复与其关联的值。所以 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 程序员……你是怎么做到的?”这个问题的答案并不是太 SCSS 。上面的 ? 暗示了答案——仔细阅读手册。此外,基本 R 代码中没有太多计算不标准的地方——公式和 library 是罪魁祸首——所以要认识到问题是什么不是有助于专注于实际发生的事情。

关于R:它能走多远? (加上通风),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36513782/

相关文章:

design-patterns - 装饰器模式的功能等效吗?

string - 获取 R 中因子中最常见的元素

在R中反复洗牌

r - 制作扩展序列的最快方法

python - 从函数式语言访问 numpy 数组

haskell - 对 (fmap length Just) [1,1,1,1] 与 fmap length $ Just [1,1,1,1] 感到困惑

r - 查找 r 中某个范围内的值并对值的数量求和

JavaScript - 始终访问特定对象的最佳方式

JavaScript 变量在传递给函数时不包含预期值

spring - 如何忽略自定义 Spring 租户