【问题标题】:Create R data with a dynamic variable name from function for package?从用于包的函数创建具有动态变量名称的 R 数据?
【发布时间】:2019-05-24 13:41:43
【问题描述】:

我正在开发一个作为包一部分的函数。 这个包包含一个新包的模板,以及一个为新包创建 R 数据的函数,该函数必须为该函数提供一个动态名称。

目前我正在做以下事情:

makedata <- function(schemeName, data) {
  rdsFile <- paste0(schemeName, ".rds")
  varName <- paste0(schemeName)
  saveRDS(
    data,
    file = file.path( ".", "data", rdsFile )
  )
  cat(
    paste0(varName, " <- readRDS(\"./", rdsFile, "\")"),
    file = file.path( ".", "data", paste0(varName, ".R") )
  )
}

makedata(name = "test", data = letters)

这导致数据目录中有两个文件:

  1. 一个文件test.rds,包含letters,但在加载包时R没有加载(不支持rds)

  2. 一个文件test.R,其代码为test &lt;- readRDS("./test.rds"),当加载包时,test.rds 中的数据将加载到包含letters 的变量test 中。

现在 CRAN 不喜欢数据目录中的 rds 文件。

还有其他方法可以使用标准格式(最好是RData)来实现吗?

【问题讨论】:

  • 我不确定我是否理解了这个问题,但也许像eval(parse(text = sprintf("save(%s, file = %s)", varName, fileLocation))) 这样的东西可以解决问题。然而,这需要将test 导出为data,这也可以使用eval parse 完成。看起来很老套,是的,所以应该存在更好的解决方案。
  • 太棒了。我绝对应该研究这些eval()parse()。如果您将此放入答案中,我会接受。可能有一些关于 parse()eval() 实际在这里做什么的信息?
  • 文件扩展名必须是.rda,而不是导出。
  • 你可能是对的,我只记得.rda 和实际变量名与文件名之间存在问题,但问题可能已经解决。不过,Eval parse 使用起来非常简单,但功能强大,如果您正在寻找代码中的动态性。正如你想象的那样,如果你在应用程序中使用它,主要问题是如果使用不小心,它会导致代码注入。 @alko989 解决方案似乎更干净
  • 感谢您的解释。我会仔细看看@alko989 解决方案。

标签: r r-package rdata


【解决方案1】:

你可以试试这样的:

makedata <- function(schemeName, data) {
  rdataFile <- paste0(schemeName, ".rda")
  ## Assign data to the name saved in schemeName
  assign(x = schemeName, value = data)
  ## Save as RData file
  save(list = schemeName, file = file.path( ".", "data", rdataFile))
}

【讨论】:

  • 这个编辑后的版本不起作用(我也试过了),因为保存会将schemeName 解释为变量,而不是变量的名称。您能否恢复到do.call() 版本,或者您编辑它的原因是什么?
  • 我改变了它,因为它更简单,它对我有用,因为它是在一个新的会话中。您必须在保存中使用参数“list = schemeName”
  • 是的 - 我忽略了list = 。谢谢。
  • 但是由于现在这是一个.rda 文件,因此不再需要带有load....R 文件。
【解决方案2】:

eval parse 的可能替代方案,如 cmets 中所述。

makedata <- function(schemeName, data) {
  rdaFile <- paste0(schemeName, ".rda")
  fileLocation <- file.path( ".", "data", rdaFile )
  varName <- paste0(schemeName)

  assign(varName, data)
  eval(parse(text = sprintf("save(%s, file = '%s')", varName, fileLocation)))

  cat(sprintf("%s <- load(%s, file = '%s')", 
              varName, varName,
              fileLocation
              ),
      file = file.path( ".", "data", paste0(varName, ".R") ))
}

题外话: 此外,由于您正在开发包,一个方便的选项可能是使用system.file 而不是file.path,因为选项system.file('data/test.R', package = 'yourPackage') 允许查看您的包目录,无论它安装在哪里。尚未测试您以前的解决方案,它可能也可以正常工作。

【讨论】:

  • 谢谢 - eval(parse()) 非常有用。但我将使用@alko989 的save(file = ...) 方法,因为它更容易理解。
  • 是的,我同意!发布此内容是因为我注意到您在使用 @alko989 解决方案时遇到了问题。很高兴你把它整理出来
  • 关于system.file():我知道(并经常使用)它,但在这里使用file.path 方法更安全。该功能包含在包中,但只能在使用此功能的包的开发过程中使用。所以使用system.file() 实际上在这里不起作用并导致错误的结果。但感谢您指出这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-29
  • 2022-01-16
  • 2017-03-18
  • 1970-01-01
  • 2019-07-25
  • 2020-10-01
  • 2017-10-22
相关资源
最近更新 更多