2014-03-28 81 views
2

我的论文数据采集过程涉及从各种开源软件库中提取数据,并将其保存为[R对象供日后分析的对象。管理来自不同来源的

为了防止已处理的数据的重新下载和再加工(大部分数据是归档),我使用digest()计算校验和(散列)用于数据源的URL,然后用比较传入的URL R数据文件以相应的校验和命名。如果一个URL的校验和与现有的R数据文件匹配,我会跳过这个URL的处理。我打算为其他来源使用类似的方法,不是通过URL检索数据,而是通过SQL查询。在这种情况下,我考虑使用digest()来计算每个数据集合SQL查询的校验和。

但是,我的主要问题是“当我想从数据文件中将R对象加载回R时,什么是最佳/最佳/正确的方法来区分R对象?。我考虑以下两种方法是:

  1. 在保存数据为R的对象的过程中,动态地创建一个查找表网址对应校验。这将允许我从R数据文件名称追踪任何校验和到​​相应的URL以及相应的数据文件(表格)。

  2. 在保存数据的过程中,请使用attr()来存储适当的信息(完整URL或仅用于基于URL的数据收集的URL文件名,或用于基于查询的数据收集的SQL查询)。

我看到的,因为它允许把URL或SQL查询信息的即时查询第一种方法(查找表)的利益,而第二种方法(属性)需要通过整个列表循环为每个数据源寻找匹配信息。同时,属性方法在保持元数据接近数据本身方面似乎更好,而查找表方法将其移动到R代码层,这创建了额外的依赖关系。

请告知这种情况和我的想法。

+0

我已经实现了我提到的(属性和查找表)这两种方法 - 只是为了看看它是多么容易 - 但后来意识到,我可以保持查找表中没有R中的代码,但作为R对象,存储在'.RData'文件。这将允许我将元数据存储在数据附近,并为不同的数据源维护不同的查找表。 –

回答

2

如果您确信您的数据源是静态的,则可以使用以下方法。否则,问题就更加困难,每次重新下载都变得不可避免,除非源代码为您提供了校验和(不需​​要提供完整的数据)。

在存储的R对象的目录中,比如说RDS格式,可以采用使用源的MD5哈希来命名文件的惯例。例如,如果

> digest("http://google.com/someRfile") 
[1] "bf01394aeea7b60cb0f5498c94d1b939" 

然后,你可以存储序列化对象出现在与名bf01394aeea7b60cb0f5498c94d1b939文件中的该URL。检查缓存命中是使用file.exists的简单方法。如果您希望将元数据附加到对象本身,则可以将该URL作为attr附加到对象。当然,这会造成慢速查找,因为您必须加载每个日期文件并检查其attr

如果你希望避免的查找表的想法(这是一个好主意!瞧到SQLite作为一个简单的本地存储),你仍然可以巧妙地加以利用的文件系统。即,而不是使文件名是MD5哈希,这是一种单向散列,使用base64编码,所以它是双向的:

> library(RCurl) 
> base64("http://google.com") 
[1] "aHR0cDovL2dvb2dsZS5jb20=" 
> base64("aHR0cDovL2dvb2dsZS5jb20=", encode = FALSE) 
[1] "http://google.com" 

可以使用base64编码字符串作为您的文件名,现在可以通过简单的base64解码文件名来轻松确定序列化对象的来源。请注意,这不会使用对象的摘要,因此您仍然可以选择将元数据附加到它。

编辑:你甚至可以结合思想的东西更聪明,消除对attr在所有的需要。也就是说,您可以使用分隔符连接R对象的MD5摘要和源URL的base64编码,如-。然后,您可以使用list.files(dir)和正则表达式来查看具有给定源的文件是否存在。另一方面,您可以从一个R对象开始,计算其MD5摘要,并通过使用不同的正则表达式(找到MD5而不是base64编码,例如^[^-]+而非[^-]+$)。

+0

罗伯特,谢谢你的回答!实际上,我最初的实现基于'digest'并将保存的R对象存储在'cache'目录中的'.RData'文件中。然后我只是使用'file.exists()'就像你在第一个建议中描述的那样。我不知道'base64'是一个双向哈希,这个建议非常有趣,并会考虑它,因为它可以避免维护查找表。顺便说一句,当你说这是个“好主意”时,你意味着什么?表现还是其他标准? –

+1

只是不要尝试'base64'编码你的R对象! MD5大小总是32个字符,但'base64'是'O(n)',其中'n'是字符串中的字符数。 –

+1

维护表是一个不错的主意,因为它更易于使用。你不必像这种方法那样知道任何约定。 –

2

你可能要检查出UNF包GitHub上。这是Universal Numeric Fingerprint algorithm的实现,实质上是数据集的格式独立散列(或签名)。这为数据提供了唯一的签名(无论变量的命名或数据集中变量的排序如何)。任何变化都会产生不同的UNF。您可以使用它来确保两个数据集是相同的。

你可以使用它,例如,创造你已经拥有的数据集UNFs的列表,计算出每一个新的数据集UNF和检查,对UNF签名的存储列表。

全面披露:我包的作者。

另请注意:截至今天(2014/03/28),并非所有R数据类型都得到完全支持(即日期和时间被视为字符串,而不是按照UNF算法规范正确处理),但这对您的目的可能无关紧要。

+0

托马斯,谢谢你的回答!我一定会详细看一下'UNF'包。从我的快速访问到你的包的GitHub页面,我的理解是'UNF'使用'base64'作为底层的主要指纹算法。由于我使用的两个主要数据源包含归档数据和相对较大的卷,因此我不认为我需要本身的数据校验和 - 对于我的目的,URL或SQL查询的校验和就足够了。但是我会在将来和我的项目的不同部分研究'UNF'的可能用例。 –

+0

托马斯,我看到你使用'Travis CI'集成来自动生成你的R包。但是,在入门指南(http://docs.travis-ci.com/user/getting-started)中我没有看到R是有效的(官方)选项。你用这个方法(http://yihui.name/en/2013/04/travis-ci-for-r)还是那个(https://github.com/craigcitro/r-travis)?或者是其他东西?谢谢! –

+1

@AleksandrBlekh我认为craigcitro的正在成为共识版本。它正处于非常活跃的发展阶段。 – Thomas