【问题标题】:Load dataset from "R" package using data(), assign it directly to a variable?使用 data() 从“R”包加载数据集,直接将其分配给变量?
【发布时间】:2015-06-20 06:55:09
【问题描述】:

如何使用 data() 函数从 R 包中加载数据集,并将其直接分配给变量,而不在您的环境中创建重复副本?

简单地说,你能做到这一点而不在你的环境中创建两个相同的 dfs:

> data("faithful") # Old Faithful Geyser Data from datasets package

> x <- faithful 

> ls() # Now I have 2 identical dfs - x and faithful - in my environment
[1] "faithful" "x" 

> remove(faithful) # Now I've removed one of the redundant dfs

尝试 1:

我的第一种方法是将data("faithful") 分配给x。但是data() 返回一个字符串。所以现在我的环境中有 df faithful 和字符向量 x

> x <- data("faithful")
> x
[1] "faithful" # String, not the df "faithful" from the datasets package

> ls()
[1] "faithful" "x"  

尝试 2: 在我的第二次尝试中尝试变得更复杂一些。

> x <- get(data("faithful")) # This works as far as assignment goes

> ls() # However I still get the duplicate copy
[1] "faithful" "x"

关于我尝试这样做的动机的简短说明。我有一个包含 5 个非常大的 data.frames 的 R 包 - 每个都有相同的列。我想在所有 5 个 data.frames 上有效地生成相同的计算列。所以我想在list() 构造函数中使用data() 将5 个data.frames 放入一个列表中。然后我想使用plyr 包中的llply()mutate() 来迭代列表中的dfs 并为每个df 创建计算列。但我不想在我的环境中放置 5 个大型数据集的重复副本,因为这是在具有 RAM 限制的 Shiny 应用程序中。


编辑: 我能够使用@henfiber 的两种方法从他的回答中找出如何将整个 data.frames 延迟加载到一个命名列表中。

这里的第一个命令用于将 data.frame 分配给一个新的变量名。

# this loads faithful into a variable x. 
# Note we don't need to use the data() function to load faithful
> delayedAssign("x",faithful) 

但我想创建一个命名列表 x,其中包含 y = data(faithful)z=data(iris) 等元素。

我尝试了以下方法,但没有成功。

> x <- list(delayedAssign("y",faithful),delayedAssign("z", iris))
> ls()
[1] "x" "y" "z" # x is a list with 2 nulls, y & z are promises to faithful & iris

但我终于能够以以下方式构造延迟加载的 data.frame 对象列表:

# define this function provided by henfiber
getdata <- function(...)
{
e <- new.env()
name <- data(..., envir = e)[1]
e[[name]]
}

# now create your list, this gives you one object "x" of class list
# with elements "y" and "z" which are your data.frames
x <- list(y=getdata(faithful),z=getdata(iris))

【问题讨论】:

  • 您可以在将数据分配到您的列表后立即删除它,例如data( "faithful" ); x &lt;- faithful; rm( faithful )
  • @vaettchen 这绝对是一个选择。只是想知道技术上是否存在跳过将额外副本加载到环境中的方法。

标签: r dataframe


【解决方案1】:

使用辅助函数:

# define this function
getdata <- function(...)
{
    e <- new.env()
    name <- data(..., envir = e)[1]
    e[[name]]
}

# now load your data calling getdata()
x <- getdata("faithful")

或者使用匿名函数:

x <- (function(...)get(data(...,envir = new.env())))("faithful")

懒惰评估

您还应该考虑将lazy loading 您的数据添加到您的包的说明文件中LazyData: true

如果您使用RStudio,在运行data("faithful") 之后,您将在Environment 面板上看到“忠实”数据帧被称为"promise"(另一个不太常见的名称是"thunk")和是灰色的。这意味着它被 R 懒惰地评估并且仍然没有加载到内存中。您甚至可以使用 delayedAssign() 函数延迟加载 "x" 变量:

data("faithful")              # lazy load "faithful"
delayedAssign("x", faithful)  # lazy assign "x" with a reference to "faithful"
rm(faithful)                  # remove "faithful"

仍然没有任何东西加载到内存中

summary(x)                    # now x has been loaded and evaluated

了解更多关于lazy evaluationhere的信息。

【讨论】:

  • 伟大的编辑!编辑后的代码听起来很有希望。我确实使用 RStudio,并注意到 promise 是如何神奇地变成内存中的对象,即使我在命令行或打开的 .R 文件中键入变量名。我目前正在做一个大的重构,但一旦完成,我会尝试你的解决方案。
  • 花点时间,如果不是公司机密,请分享您的反馈 - 以及您的 shiny 应用程序 :)
  • 谢谢。您对delayedAssign 的编辑非常完美。虽然它并不真正适用于我构建一个值等于加载数据集的命名列表的想法,但它回答了这个问题。
  • 其实你甚至不需要data("faithful")rm(faithful)。我在没有任何上下文的情况下尝试了delayedAssign("x", faithful),它只是工作......
  • @aashanand 你是对的!并且由于delayedAssign() 所做的只是懒惰eval() 第二个参数中的表达式,因此以下工作也可以:x &lt;- eval(faithful)。这可能只是您原始问题的答案(加载faithful,但分配给x)。
【解决方案2】:

为什么不使用这样的简单解决方案:

x <- list(y = datasets::faithful, z = datasets::iris )

【讨论】:

    猜你喜欢
    • 2013-11-23
    • 2016-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多