R中具有不同摘要的相同数据帧?

Ite*_*tor 7 hash r dataframe

我有两个大的数据帧,ab为这identical(a,b)TRUE按原样all.equal(a,b),不过identical(digest(a),digest(b))FALSE.什么可能导致这个?

更重要的是,我试图通过将摘要应用于一堆行来深入挖掘.令人难以置信的是,至少在我看来,子帧的摘要值一直到数据帧的最后一行是一致的.

这是一系列比较:

> identical(a, b)
[1] TRUE
> all.equal(a, b)
[1] TRUE
> digest(a)
[1] "cac56b06078733b6fb520442e5482684"
> digest(b)
[1] "fdd5ab78ca961982d195f800e3cf60af"
> digest(a[1:nrow(a),])
[1] "e44f906723405756509a6b17b5949d1a"
> digest(b[1:nrow(b),])
[1] "e44f906723405756509a6b17b5949d1a"
Run Code Online (Sandbox Code Playgroud)

我能想到的每个方法都表明这两个对象是相同的,但它们的摘要值是不同的.数据框还有其他可以产生这种差异的东西吗?


有关详细信息:对象大约是10M行x12列.这是输出str():

'data.frame':   10056987 obs. of  12 variables:
 $ V1 : num  1 11 21 31 41 61 71 81 91 101 ...
 $ V2 : num  1 1 1 1 1 1 1 1 1 1 ...
 $ V3 : num  2 3 2 3 4 5 2 4 2 4 ...
 $ V4 : num  1 1 1 1 1 1 1 1 1 1 ...
 $ V5 : num  1.8 2.29 1.94 2.81 3.06 ...
 $ V6 : num  0.0653 0.0476 0.0324 0.034 0.0257 ...
 $ V7 : num  0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 ...
 $ V8 : num  0.00653 0.00476 0.00324 0.0034 0.00257 ...
 $ V9 : num  1.8 2.3 1.94 2.81 3.06 ...
 $ V10: num  0.1957 0.7021 0.0604 0.1866 0.9371 ...
 $ V11: num  1704 1554 1409 1059 1003 ...
 $ V12: num  23309 23309 23309 23309 23309 ...

> print(object.size(a), units = "Mb")
920.7 Mb
Run Code Online (Sandbox Code Playgroud)

更新1:一时兴起,我将这些转换为矩阵.摘要是相同的.

> aM = as.matrix(a)
> bM= as.matrix(b)
> identical(aM,bM)
[1] TRUE
> digest(aM)
[1] "c5147d459ba385ca8f30dcd43760fc90"
> digest(bM)
[1] "c5147d459ba385ca8f30dcd43760fc90"
Run Code Online (Sandbox Code Playgroud)

然后我尝试转换回数据帧,并且摘要值相等(并且等于之前的值a).

> aMF = as.data.frame(aM)
> bMF = as.data.frame(bM)
> digest(aMF)
[1] "cac56b06078733b6fb520442e5482684"
> digest(bMF)
[1] "cac56b06078733b6fb520442e5482684"
Run Code Online (Sandbox Code Playgroud)

所以,b看起来像坏男孩,它有一个丰富多彩的过去. b比如,来自更大的数据框架B.我只拿了B出现的那些列a并检查它们是否相等.嗯,他们是平等的,但有不同的摘要.我转换了列名称(从"InformativeColumnName1"到"V1"等),只是为了避免可能出现的任何问题 - 尽管all.equal并且identical在列名称不同时倾向于指出.

由于我正在处理两个不同的程序而且没有同时访问ab,因此最简单的方法是使用摘要值来检查计算.但是,如何从数据框中提取列然后应用于digest()它,似乎有些奇怪.


答案: 事实证明,令我惊讶的是(沮丧,恐怖,尴尬,你的名字),identical对属性非常宽容.我原以为只是all.equal对属性的宽容.

这是通过汤米的建议发现的identical(d1, d2, attrib.as.set=FALSE).运行attributes(a)是一个糟糕的坏主意:在Ctrl-C可以中断之前,行名称泛滥需要一段时间.这是输出names(attributes()):

> names(attributes(a))
[1] "names"     "row.names" "class"    
> names(attributes(b))
[1] "names"     "class"     "row.names"
Run Code Online (Sandbox Code Playgroud)

他们的订单不同!digest()感谢我和我直接相处.

UPDATE

为了帮助其他人解决这个问题,似乎只需重新排列属性即可获得相同的哈希值.由于修改属性订单对我来说是新的,这可能会破坏某些东西,但它适用于我的情况.请注意,如果对象很大,则需要花费一些时间.我不知道更快的方法.(我也希望转向使用矩阵或数据表而不是数据帧,这可能是避免数据帧的另一个动机.)

tmpA0   = attributes(a)
tmpA1   = tmpA0[sort(names(tmpA0))]
a2      = a
attributes(a2) = tmpA1

tmpB0   = attributes(b)
tmpB1   = tmpB0[sort(names(tmpB0))]
b2      = b
attributes(b2) = tmpB1

digest(a2)  # e04e624692d82353479efbd713ec03f6
digest(b2)  # e04e624692d82353479efbd713ec03f6

identical(b,b2, attrib.as.set = FALSE) # FALSE
identical(b,b2, attrib.as.set = TRUE) # TRUE
identical(a2,b2, attrib.as.set = FALSE) # TRUE
Run Code Online (Sandbox Code Playgroud)

Tom*_*mmy 8

如果没有实际的data.frames,当然很难知道,但一个区别可能是属性的顺序.identical默认情况下忽略该设置,但设置attrib.as.set=FALSE可以更改:

d1 <- structure(1, foo=1, bar=2)
d2 <- structure(1, bar=2, foo=1)

identical(d1, d2) # TRUE
identical(d1, d2, attrib.as.set=FALSE) # FALSE
Run Code Online (Sandbox Code Playgroud)


Dir*_*tel 7

我们的摘要包使用内部R函数serialize()来获取我们为哈希生成函数(md5,sha1,...)提供的内容.

所以我强烈怀疑可能有类似属性的东西不同.除非你能够构建一个不依赖于你的1e7 x 12数据集的可重现的东西,否则我们无能为力.

此外,该digest()函数可以输出中间结果和(截至最近的0.5.1版本)偶数raw向量.这可能有所帮助.最后,您可以随时联系我们(作为软件包维护人员/作者)离线,这恰好是R land中的推荐方式,StackOverflow的普及程度无法承受.