为什么在 R 中使用 dplyr 后 data.frame 的摘要会发生变化?

Why is the digest of a data.frame changed after the use of dplyr in R?

我假设如果我有 2 个相同的 data.frames,R 摘要函数应该 return 相同的结果。考虑这两个数据框。

library(digest)
library(dplyr)
df1 <- tibble(a =1:5, b=11:15)
df2 <-  df1 %>% 
        mutate(c=b-1) %>% 
        select(-c)

两者 data.frames 打印时完全相同,

> df1
# A tibble: 5 × 2
  a     b
  <int> <int>
1     1    11
2     2    12
3     3    13
4     4    14
5     5    15

或比较:

> df1 ==df2
        a    b
[1,] TRUE TRUE
[2,] TRUE TRUE
[3,] TRUE TRUE
[4,] TRUE TRUE
[5,] TRUE TRUE

然而,摘要函数 returns 不同的结果:

> digest(df1)
[1] "4f82aa1035792a0acf304242ce6ad3ec"
> digest(df2)
[1] "3b7e697af67e8e36ba9b59aef69db304"

我希望摘要函数产生相同的结果!! 有没有更好的方法来比较相同的 data.frames?

我不太了解 digest,但是 attributes 的顺序发生了变化,可能是因为 names 最后更新了:

attributes(df1)
$names
[1] "a" "b"

$class
[1] "tbl_df"     "tbl"        "data.frame"

$row.names
[1] 1 2 3 4 5
attributes(df2)
$class
[1] "tbl_df"     "tbl"        "data.frame"

$row.names
[1] 1 2 3 4 5

$names
[1] "a" "b"

我不知道为什么 digest 两者不同。然而,重要的是要注意,这不仅仅发生在 dplyr

df3 <- df1
df3$c <- 1
df3 <- df3[ ,-3]

digest(df3)

returns第三个唯一值

75f29cee80971220081372627632689f

尽管有趣的是 df4 <- df1[,1:2]digest 是相同的。我什至可以使用 df1df2 生成相同的散列:

digest(df1[,1:2])
digest(df2[,1:2])

以及 "f111f4b3d65b8bc2569a4b79a821a6d8" 与

的不同(共享)散列
digest(as.data.frame(df1[,1:2]))
digest(as.data.frame(df2[,1:2]))

它一定与 R 在将变量存储在内存中时如何处理变量的创建有关。我的理解是 digest 不是在 内给出值的散列 变量而是变量本身的散列。因此,您可能需要添加一个步骤,以相同的方式生成变量以使哈希一致。

但是,如果您正在寻找不同的比较方式,我建议 all_equal 来自 dplyr

all_equal(df1, df2)

returns TRUE 并允许对边缘情况进行一些处理(例如,默认情况下它不关心行或列是否重新排列)。如果您的目标只是检查两个数据集的一致性,这可能是一种 "better" 方式,而不是与 digest

作斗争