27

我被要求更改当前导出 .Rdata 文件的软件,以便它以“与平台无关的二进制格式”导出,例如 HDF5 或 netCDF。给出了两个原因:

  1. Rdata 文件只能由 R 读取
  2. 二进制信息的存储方式因操作系统或体系结构而异

我还发现 “R Data import export manual”没有讨论 Rdata 文件,尽管它确实讨论了 HDF5 和 netCDF。

关于 R-help的讨论表明 .Rdata 文件是独立于平台的。

问题:

  1. 这些担忧在多大程度上是有效的?
    • 例如,Matlab 可以在不调用 R 的情况下读取 .Rdata 吗?
  2. 在这方面,其他格式是否比 .Rdata 文件更有用?
  3. 是否可以编写一个脚本来创建所有 .Rdata 文件的 .hdf5 类似物,从而最大限度地减少对程序本身的更改?
4

4 回答 4

28

这里有各种各样的答案:

  1. 丰富的选择首先,这个问题是有道理的,但是你的选择列表比它应该的要窄一些。HDF5/netCDF4 是一个很好的选择,可以很好地与 Python、Matlab 和许多其他系统配合使用。HDF5 在很多方面都优于 Python 的 pickle 存储——看看 PyTables,你很可能会看到很好的加速。Matlab 曾经(并且可能仍然存在)一些关于如何将大单元(或可能是结构)数组存储在 HDF5 中的问题。不是它做不到,而是它慢得可怕。这是 Matlab 的问题,而不是 HDF5 的问题。虽然这些都是不错的选择,但您也可以考虑 HDF5 是否足够:考虑您是否有一些非常大的文件并且可以从专有编码中受益,无论是访问速度还是压缩。它'bigmemory(即访问速度)。事实上,您甚至可以使用bigmemory其他语言的文件——这确实是一种非常简单的格式。HDF5 无疑是一个很好的起点,但没有一种通用的数据存储和访问解决方案,尤其是在处理非常大的数据集时。(对于较小的数据集,您还可以查看 Protocol Buffers 或其他序列化格式;Dirk 曾RProtoBuf在 R 中访问这些格式。)对于压缩,请参阅下一个建议。

  2. 尺寸正如 Dirk 所提到的,文件格式可以描述为应用程序中立和应用程序相关。另一个轴是域无关(或域无知)或域相关(域智能;-))存储。如果您对数据的生成方式有一定的了解,尤其是任何可用于压缩的信息,您可能能够构建比标准压缩器所能做的任何事情更好的格式。这需要一些工作。gzip 和 bzip 之外的替代压缩器还允许您分析大量数据并开发适当的压缩“字典”,以便您可以获得比 .Rdat 文件更好的压缩。对于许多类型的数据集,将不同行之间的增量存储在一个表中是一个更好的选择——它可以带来更大的可压缩性(例如,可能会出现很多 0),

  3. 速度和访问 .Rdat 不支持随机访问。它没有对并行 I/O 的内置支持(尽管如果您愿意,您可以串行化到并行 I/O 存储)。在这里可以做很多事情来改进事情,但是一次又一次地将东西粘贴到 .Rdat 上需要千刀万剐,而不是仅仅切换到不同的存储机制并消除速度和访问问题。(这不仅仅是 HDF5 的优势:我经常使用多核函数来并行化其他 I/O 方法,例如bigmemory。)

  4. 更新功能R 没有很好的方法来将对象添加到 .Rdat 文件。据我所知,它没有提供任何“查看器”来允许用户直观地检查或搜索 .Rdat 文件的集合。据我所知,它不提供文件中对象的任何内置版本控制记录保存。(我通过文件中的一个单独对象执行此操作,该对象记录生成对象的脚本版本,但我将在未来的迭代中将其外包给 SQLite。)HDF5 具有所有这些。(此外,随机访问会影响数据的更新 - .Rdat 文件,您必须保存整个对象。)

  5. 社区支持尽管我提倡您自己的格式,但这是针对极端数据大小的。为多种语言构建库对于减少交换数据的摩擦非常有帮助。对于大多数简单的数据集(在大多数情况下,简单仍然意味着“相当复杂”)或中等到相当大的数据集,HDF5 是一种很好的格式。当然,有办法在专门的系统上击败它。尽管如此,它仍然是一个很好的标准,并且意味着将花费更少的组织工作来支持专有或特定于应用程序的格式。在使用生成数据的应用程序之后,我已经看到组织多年来一直坚持使用一种格式,只是因为编写了太多代码来加载和保存该应用程序的格式,并且 GB 或 TB 的数据已经以其格式存储(这可能是你和 R 的某一天,但这源于不同的统计套件,它以字母“S”开头并以字母“S”结尾;-))。这对未来的工作来说是一个非常严重的摩擦。如果您使用一种广泛使用的标准格式,那么您可以更轻松地在它和其他广泛使用的标准之间进行移植:很可能其他人也决定解决同样的问题。试一试 - 如果您现在使用转换器,但实际上并没有将其转换以供使用,至少您已经创建了一个工具,如果有必要转移到另一种数据格式,其他人可以使用它. 然后,您可以更轻松地在它和其他广泛的标准之间进行移植:很可能其他人也决定解决同样的问题。试一试 - 如果您现在使用转换器,但实际上并没有将其转换以供使用,至少您已经创建了一个工具,如果有必要转移到另一种数据格式,其他人可以使用它. 然后,您可以更轻松地在它和其他广泛的标准之间进行移植:很可能其他人也决定解决同样的问题。试一试 - 如果您现在使用转换器,但实际上并没有将其转换以供使用,至少您已经创建了一个工具,如果有必要转移到另一种数据格式,其他人可以使用它.

  6. 内存使用 .Rdat 文件,您必须loadattach它才能访问对象。大多数时候,人们load整理文件。好吧,如果文件很大,就会有很多 RAM。因此,无论是使用attach对象还是将对象分成多个文件,都更聪明一些。这对于访问对象的一小部分是相当麻烦的。为此,我使用内存映射。HDF5 允许随机访问文件的某些部分,因此您无需加载所有数据只是为了访问一小部分。这只是事情运作方式的一部分。因此,即使在 R 中,也有比 .Rdat 文件更好的选择。

  7. 转换脚本至于您关于编写脚本的问题 - 是的,您可以编写一个脚本来加载对象并将它们保存到 HDF5 中。但是,对大量异构文件执行此操作并不一定是明智的,除非您对将要创建的内容有很好的了解。我无法开始为我自己的数据集设计这个:那里有太多一次性对象,创建一个庞大的 HDF5 文件库将是荒谬的。最好把它想象成一个数据库:你想存储什么,你将如何存储它,以及它将如何表示和访问?

一旦您制定了数据转换计划,您就可以使用 Hadoop 之类的工具甚至是基本的多核功能来释放您的转换程序并尽快完成这项工作。

In short, even if you stay in R, you are well advised to look at other possible storage formats, especially for large, growing, data sets. If you have to share data with others, or at least provide read or write access, then other formats are very much advised. There's no reason to spend your time maintaining readers/writers for other languages - it's just data not code. :) Focus your code on how to manipulate data in sensible ways, rather than spend time working on storage - other people have done a very good job on that already.

于 2011-10-25T14:02:22.637 回答
9

(二进制)文件格式有两种基本风格:

  • application-neutral,由公共库和 API 支持(netCDF 和 HDF5 都属于这个阵营),如果它们通过使用 API 的附加包进行扩展,则可以促进不同程序和应用程序之间的数据交换

  • 特定于应用程序的应用程序仅设计用于一个程序,尽管效率更高:这就是 .RData 所做的

因为 R 是开源的,你可以从你的 Matlab 文件中重新创建 RData 的格式:没有什么能阻止你编写一个合适的 mex 文件。也许有人甚至已经这样做了。没有技术上的理由不尝试——但如果两个应用程序都打算共享数据,那么另一条路线可能会更容易支持该格式。

值得一提的是,早在 1990 年代初期/中期,我确实编写了自己的 C 代码来编写 Octave 使用的二进制格式的模拟文件(然后我使用它对数据进行切片)。能够使用开源软件做到这一点是一大优势。

于 2011-10-20T17:37:16.793 回答
5

我想我可以回答一些,但不是所有这些问题。

  1. 好吧,任何下定决心的人都可以.Rdata直接读取文件,但这是一项艰苦的工作,而且没有太多好处。所以我怀疑Matlab已经做到了。您可能还记得,R 可以读取各种其他系统格式,正是因为有人为此付出了很多努力。

  2. 对于文本格式,csv 看起来很“标准”,但对于二进制格式,我不知道——而且 csv 不是一个好的标准——它(尤其是)日期和引号的处理方式差异很大(当然它只适用于数据表)。

  3. 当然!

例子:

for(f in list.files(".", pattern="\\.Rdata$") {
    e <- new.env()
    load(f, e)       # load all values into environment e
    x <- as.list(e)

    #saveInOtherFormat(x, file=sub("\\.Rdata$", ".Other", f))
}
于 2011-10-20T16:02:55.677 回答
4

第 2 点是错误的:二进制 .RData 文件跨硬件和操作系统平台移植。引用 ?save 的帮助页面:

所有 R 平台都在二进制 save-d 文件中使用 C ints 和 doubles 的 XDR(biendian)表示,并且它们可以在所有 R 平台上移植。

第 1 点是数据是什么的函数,以及可能对数据有用的其他程序。如果您的代码库使用 save() 来编写指定的对象,即数据帧或矩阵,您可以轻松编写一个小函数 save2hdf() 将它们写为 hdf 或 ncdf 二进制文件,然后使用 sed 将所有出现的 save( 更改为save2hdf( 在你的代码库中。至少 ncdf 会对读取性能产生影响,但不会太糟糕。如果你的代码使用保存对象,如异构对象列表,你可能无法使用 ncdf 或 hdf 没有一个很好的处理重新编码以写出单独的组件对象。

另请注意,netCDF 4 在 R 中仍然存在问题。

于 2011-10-24T22:19:03.250 回答