打包大数据集

krl*_*mlr 5 r devtools

inst/extdata正如Jan建议的那样,现在在dfunbindpackage中实现了按列存储在package目录中。

我正在使用这种data-raw惯用法来使从原始数据到结果的整个分析都可重现。为此,数据集首先包装在R包中,然后可以使用加载library()

我使用的数据集之一比较庞大,大约有800万个观测值,其中包含约80个属性。对于当前的分析,我只需要一小部分属性,但是无论如何我都希望打包整个数据集。

现在,如果将其简单地打包为数据帧(例如,使用devtools::use_data()),则在首次访问它时将全部加载。打包此类数据以使我可以在列级别进行延迟加载的最佳方法是什么?(只有我实际访问的那些列被加载,其他列愉快地保留在磁盘上并且不占用RAM。)ff程序包对您有帮助吗?谁能指出我的工作范例?

Jan*_*aan 5

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

然后的问题是,您以何种格式存储数据,以及如何在不读取内存中数据的情况下从中获取选择。为此,有很多选择。列举一些:

  • sqlite:将您的数据存储在sqlite数据库中。然后,您可以使用rsqlite包对该数据执行查询。
  • ff:将数据存储在ff对象中(例如,使用save.ffdffrom中的函数进行保存ffbase;用于load.ffdf再次加载)。ff不能很好地处理字符字段(它们总是转换为因子)。从理论上讲,文件不是跨平台的,尽管只要您停留在intel平台上就可以。
  • 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)
Run Code Online (Sandbox Code Playgroud)

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

library(lazyload)
data <- load_data("iris", "Sepal.Width")
Run Code Online (Sandbox Code Playgroud)

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

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