我的论文数据收集过程涉及从各种开源软件存储库中提取数据并将其保存为 R对象以供将来分析。
为了防止重新下载和重新处理已处理的数据(大部分数据都是存档的),我使用digest()
计算数据源的校验和(哈希) URL,然后将传入的URL与以相应校验和命名的R数据文件进行比较。如果URL的校验和与现有的R数据文件匹配,则跳过此URL的处理。我计划对另一个源使用类似的方法,数据不是通过URL检索,而是通过SQL查询检索。在这种情况下,我考虑使用digest()
来计算每个数据集合SQL查询的校验和。
然而,我的主要问题是&#34;当我想要将R对象从数据文件加载回R时,最佳/最佳/正确的方法是什么?&#34; < / strong>即可。我正在考虑以下两种方法:
在将数据保存为R对象的过程中,使用 URL 和相应的校验和动态创建查找表。这样我就可以跟踪从R数据文件名到相应URL的任何校验和,从而跟踪相应的数据文件(表)。
在保存数据的过程中,使用attr()
存储相应的信息(完整的URL或URL的基于URL的数据集的文件名,或查询的SQL查询)基于数据收集)。
我看到第一种方法(查找表)的好处在于它允许立即查找所需的URL或SQL查询信息,而第二种方法(属性)需要循环遍历每个数据源的整个列表,以便查找匹配的信息。同时,属性方法在保持元数据接近数据本身方面似乎更好,而查找表方法将其移动到R代码层,这会创建额外的依赖性。
请告知这种情况和我的想法。
答案 0 :(得分:2)
如果您确信数据源是静态的,则可以使用以下方法。否则,问题就更难了,每次重新下载都是不可避免的,除非源为你提供校验和(不提取完整数据)。
在存储的R对象的目录中,比如RDS格式,您可以采用使用源的MD5哈希来命名文件的约定。例如,如果
> digest("http://google.com/someRfile")
[1] "bf01394aeea7b60cb0f5498c94d1b939"
然后,您可以将该URL处的序列化对象存储在名为bf01394aeea7b60cb0f5498c94d1b939
的文件中。然后检查缓存命中就是使用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编码,例如{{1)来轻松确定它是否已经缓存而不是^[^-]+
)。
答案 1 :(得分:2)
您可能想查看GitHub上的UNF包。这是Universal Numeric Fingerprint algorithm的实现,实质上是数据集的与格式无关的散列(或签名)。这为数据提供了唯一的签名(无论变量命名或数据集中变量的排序如何)。任何改变都会产生不同的UNF。您可以使用它来确保两个数据集完全相同。
例如,您可以使用它来为您已有的数据集创建UNF列表,计算每个新数据集上的UNF,并根据存储的UNF签名列表进行检查。
完全披露:我是包裹作者。
另请注意:截至今天(2014/03/28),并非所有R数据类型都得到完全支持(即日期和时间被视为字符串,而不是按照UNF算法规范正确处理),但这可能对你的目的无关紧要。