【问题标题】:What are the disadvantages of using .Rdata files compared to HDF5 or netCDF?与 HDF5 或 netCDF 相比,使用 .Rdata 文件有哪些缺点?
【发布时间】:2011-12-11 21:19:06
【问题描述】:

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

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

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

discussion on R-help 建议 .Rdata 文件与平台无关。

问题:

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

【问题讨论】:

  • 您无法存储 .Rdata 可以存储的所有类型的 R 对象。如果它只是值数组和通常的维度元数据,应该没有问题,但它仍然不会是一对一的替换。您真的是指所有 .Rdata 文件吗?
  • @mdsumner 你说得很好。我有一些对象是列表和数据框列表或特殊类对象列表(如函数,mcmc.objects),它们在其他应用程序中可能或多或少有用。我可能会保留 Rdata 格式的函数,或者我可以将它们打印为文本文件以用于文档记录。 mcmc.objects 我可以先转换。
  • 这真的取决于你的听众。除了通常用于统计计算之外,我对 R 了解不多,但如果您要导出地理空间和/或科学数据,您的客户可能需要 NetCDF。

标签: r file-format hdf5 netcdf


【解决方案1】:

这里有各种各样的答案:

  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 之类的工具甚至是基本的多核功能来释放您的转换程序并尽快完成。

简而言之,即使您留在 R,建议您查看其他可能的存储格式,尤其是对于大型、不断增长的数据集。如果您必须与他人共享数据,或者至少提供读取或写入访问权限,那么非常建议使用其他格式。没有理由花时间维护其他语言的读取器/写入器 - 这只是数据而不是代码。 :) 将您的代码重点放在如何以合理的方式操作数据上,而不是将时间花在存储上——其他人已经在这方面做得很好。

【讨论】:

  • 不错且详细的答案。我必须指出,Protocol Buffers 并不是作为一种 storage 机制而发明的,而是用于不同系统(和语言)之间的通信。 RProtoBuf 的大小写也不同。 :)
  • @DirkEddelbuettel 哎呀,现在每个人都会得到 eRRoR。 :) 你对存储问题的看法是正确的——我突然想到它对小对象很有用,尤其是那些可能自然地在内存中、程序之间或机器之间传递的对象。
  • @Iterator 我不知道您可以将attach 与.RData 文件一起使用。您能否就此提供更多信息(或指向某些信息的指针)?您的回答似乎表明这不会通过提前加载来使用 RAM。当我尝试这个时,虽然我没有看到 RAM 使用量激增,但我的 R 会话变得相当无响应。附加前是否扫描整个文件?
【解决方案2】:

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

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

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

还要注意 netCDF 4 在 R 中仍然存在问题。

【讨论】:

  • +1 感谢您的澄清。字符向量可能要复杂得多(编码等),但我想 NetCDF/HDF 无论如何都无法处理它们......
【解决方案3】:

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

  • 应用程序中立,由公共库和 API 支持(netCDF 和 HDF5 都属于这一阵营),这有助于之间的数据交换不同的程序和应用程序,前提是它们通过使用 API 的附加包进行扩展

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

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

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

【讨论】:

  • 感谢您澄清这一区别;现在我明白了。
  • 没有提到Rprotobuf?别担心,我为你插上了。 :)
【解决方案4】:

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

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

  2. 1234563当然它只适用于数据表)。
  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))
}

【讨论】:

  • 在这里您可能要检查加载的对象是否属于可以以新格式成功保存的类型,否则排除/警告...
  • 对于二进制格式,请查看协议缓冲区和Rprotobuf,它们是由偶尔出现在 SO 上的一些人开发的。 :)
猜你喜欢
  • 1970-01-01
  • 2018-02-13
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 2013-05-30
  • 1970-01-01
  • 2020-11-20
  • 2022-10-20
相关资源
最近更新 更多