【问题标题】:Identical data frames with different digests in R?R中具有不同摘要的相同数据帧?
【发布时间】:2011-09-28 15:05:31
【问题描述】:

我有两个大数据框,ab,其中 identical(a,b)TRUEall.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"

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


有关详细信息:对象约为 10M 行 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"

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

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

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

由于我正在处理两个不同的程序并且不能同时访问ab,因此我最容易使用摘要值来检查计算。但是,我如何从数据框中提取列然后将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

【问题讨论】:

  • 我进行了更多实验,似乎当您对data.frame(例如a[,1:3])的列进行子集化时,您会更改属性的顺序!
  • @Tommy:谢谢!我刚刚发现与行相同的东西。 R 很狡猾。

标签: r hash dataframe


【解决方案1】:

如果没有实际的 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

【讨论】:

  • 哇,这到底是什么?!这似乎解决了它。 (将修改问题以显示这一点。)
【解决方案2】:

我们的 digest 包使用内部 R 函数 serialize() 来获取我们提供给哈希生成函数(md5、sha1、...)的内容。

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

此外,digest() 函数可以输出中间结果和(从最近的 0.5.1 版本开始)甚至是raw 向量。这可能会有所帮助。 最后,您可以随时与我们(​​作为包维护者/作者)离线联系,这恰好是 R 领域内推荐的方式,但 StackOverflow 的受欢迎程度无法承受。

【讨论】:

  • 不幸的是,我什至无法生成此异常的子集或任何可重现的示例,从而导致此异常。如果可以的话,我会的。唉,对于我的数据来说,SO 的边距太小了。我还怀疑问题不在digest 之外:如果转换为矩阵使一切正常(或选择子帧),那么它让我认为数据被巧妙地转换了。换句话说,我不知道digest 是不是在说真话,但identical 是在骗我。 :) 我习惯了all.equal 非常宽容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-22
  • 1970-01-01
  • 2021-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多