R中具有不同摘要的相同 Dataframe ?

cclgggtu  于 2023-03-10  发布在  其他
关注(0)|答案(3)|浏览(113)

我有两个大 Dataframe ab,其中identical(a,b)TRUEall.equal(a,b)也是all.equal(a,b),但是identical(digest(a),digest(b))FALSE
此外,我试图通过将摘要应用于一串行来更深入地挖掘,令人难以置信的是,至少对我来说,子帧上的摘要值一直到 Dataframe 的最后一行都是一致的。
下面是一系列比较:

> 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"

我能想到的每种方法都表明这两个对象是相同的,但它们的摘要值不同。数据框中是否还有其他因素会产生这样的差异?
更多详情:对象大约是10 M行x 12列。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

更新1:一时兴起,我把这些转换成矩阵。摘要是一样的。

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

然后,我尝试转换回 Dataframe ,摘要值相等(等于a的前一个值)。

> aMF = as.data.frame(aM)
> bMF = as.data.frame(bM)
> digest(aMF)
[1] "cac56b06078733b6fb520442e5482684"
> digest(bMF)
[1] "cac56b06078733b6fb520442e5482684"

所以,b看起来像坏男孩,它有一个丰富多彩的过去。b来自一个更大的 Dataframe ,比如B。我只取B中出现在a中的列,并检查它们是否相等。但是有不同的摘要。我把列名(从“信息栏名称1”到“V1”等),只是为了避免可能出现的任何问题-尽管all.equalidentical倾向于指出列名不同的情况。
由于我正在运行两个不同的程序,并且不能同时访问ab,所以使用摘要值来检查计算结果对我来说是最简单的,但是,我从 Dataframe 中提取列,然后将digest()应用到它的方式似乎有些奇怪。

**回答:**结果,令我惊讶(沮丧、恐惧、尴尬,你能想到的都有)的是,identical对属性非常宽容,我以为只有all.equal对属性宽容。

这是通过Tommy的建议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"

他们的顺序不同!digest()对我直言不讳。

更新

为了帮助其他人解决这个问题,似乎简单地重新排列属性就足以得到相同的散列值。由于修改属性顺序对我来说是新的,这可能会破坏一些东西,但在我的情况下是有效的。注意,如果对象很大,这会消耗一些时间;我还不知道有什么更快的方法可以做到这一点(我也希望使用矩阵或数据表来代替数据框架,这可能是避免使用数据框架的另一个动机)。

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
wlsrxk51

wlsrxk511#

如果没有实际的数据.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
9rnv2umw

9rnv2umw2#

我们的digest包使用内部R函数serialize()来获取我们提供给哈希生成函数(md5、sha1...)的内容。
所以我强烈怀疑可能会有一些像属性不同的东西。除非你能构造出不依赖于你的1 e7 x 12数据集的可复制的东西,否则我们能做的很少。
另外,digest()函数可以输出中间结果,甚至可以输出raw向量(从最近的0.5.1版本开始),这可能会有帮助。最后,您可以随时离线联系我们(作为软件包维护者/作者),这恰好是R land推荐的方式,尽管StackOverflow很受欢迎。

a11xaf1n

a11xaf1n3#

如果从现有数据框重新生成数据框,属性的顺序将重置,如下所示:

reset.data.frame = data.frame(col1 = prob.data.frame$col1, 
                              col2 = prob.data.frame$col2) # etc.

因此,您只需在每次哈希之前使用此技巧重置属性,它应该可以正常工作

相关问题