打包一个大型数据集

时间:2014-11-05 09:25:49

标签: r devtools

  

程序包的inst/extdata目录中的逐列存储,suggested by Jan,现在已在dfunbind package中实现。

我使用data-raw idiom从原始数据到结果可重复进行整个分析。为此,数据集首先包装在R包中,然后可以使用library()加载。

我使用的其中一个数据集很大,大约有800万个观测值,大约有80个属性。对于我目前的分析,我只需要一小部分属性,但我还是要打包整个数据集。

现在,如果将其简单地打包为数据帧(例如,使用devtools::use_data()),则在首次访问时将完整地加载它。打包这种数据的最佳方法是什么,以便我可以在列级别进行延迟加载? (只有我实际访问的那些列才会被加载,其他列很高兴留在磁盘上并且不会占用RAM。)ff package会有帮助吗?有人能指出我一个有效的例子吗?

1 个答案:

答案 0 :(得分:4)

我想,我会将数据存储在inst/extdata中。然后在包中创建一些可以读取和返回部分数据的函数。在您的功能中,您可以使用system.file("extdata", "yourfile", package = "yourpackage")获取数据路径。 (与您链接的页面一样)。

问题在于您存储数据的格式,以及如何在不读取内存中的数据的情况下从中获取选择。为此,有很多选择。为某些人命名:

  • sqlite :将您的数据存储在sqlite数据库中。然后,您可以使用rsqlite包对此数据执行查询。
  • ff :将您的数据存储在ff个对象中(例如,使用save.ffdf中的ffbase函数进行保存;再次使用load.ffdf加载) 。 ff没有很好地处理字符字段(它们总是转换为因子)。从理论上讲,这些文件并不是跨平台的,尽管只要你留在英特尔平台上就应该没问题。
  • CSV :将您的数据存储在普通的旧csv文件中。您可以使用LaF包从此文件中进行选择。性能可能会低于ff,但可能还不错。
  • RDS :将每个列存储在单独的RDS文件中(使用saveRDS)并使用readRDS加载它们的优点是您确实依赖于任何R-包。这很快。缺点是您无法进行行选择(但似乎并非如此)。

如果您只想选择列,我会使用RDS。

使用RDS的粗略示例

以下代码创建一个包含虹膜数据集的示例包:

load_data <- function(dataset, columns) { 
  result <- vector("list", length(columns));
  for (i in seq_along(columns)) {
    col <- columns[i]
    fn <- system.file("extdata", dataset, paste0(col, ".RDS"), package = "lazydata")
    result[[i]] <- readRDS(fn)
  }
  names(result) <- columns
  as.data.frame(result)
}

store_data <- function(package, name, data) {
  dir <- file.path(package, "inst", "exdata", name)
  dir.create(dir, recursive = TRUE)
  for (col in names(data)) {
    saveRDS(data[[col]], file.path(dir, paste0(col, ".RDS")))
  }
}

packagename <- "lazyload"
package.skeleton(packagename, "load_data")
store_data(packagename, "iris", iris)

在构建和安装软件包之后(您需要修复文档,例如删除它),您可以执行以下操作:

library(lazyload)
data <- load_data("iris", "Sepal.Width")

加载虹膜数据集的Sepal.Width列。

当然这是load_data的一个非常简单的实现:没有错误处理,它假定所有列都存在,它不知道哪些列存在,它不知道存在哪些数据集。