【问题标题】:Possible bug in R all.equalR all.equal 中可能存在的错误
【发布时间】:2012-09-09 07:48:46
【问题描述】:

我在 R 的 all.equal 函数中遇到了一些奇怪的行为。基本上,我以不同的方式创建两个相同的 data.frame,然后调用 all.equal 函数(同时检查数据和属性)。

重现该行为的代码如下:

var.a <- data.frame(cbind(as.integer(c(1,5,9)), as.integer(c(1,5,9))))
colnames(var.a) <- c("C1", "C2")
rownames(var.a) <- c("1","5","9")

var.b <- data.frame(matrix(NA, nrow = 10, ncol = 2))
var.b[, 1] <- 1:10
var.b[, 2] <- 1:10
colnames(var.b) <- c("C1", "C2")
var.b <- var.b[seq(1, nrow(var.b), 4), ]

all.equal(var.a, var.b)

这是一个错误还是我只是错过了什么?我对 all.equall 函数做了一些调试,看来问题出在 data.frames 的行名上(一旦它们是字符,而其他时候是数字向量)。 all.equall 函数的响应:

[1]“属性:”
[2]“属性:"

然而,

typeof(rownames(var.a)) == typeof(rownames(var.b))

返回 TRUE,这让我很困惑。

P.S.:对象的结构似乎相同:

> str(var.a)
'data.frame':   3 obs. of  2 variables:
$ C1: int  1 5 9
$ C2: int  1 5 9
> str(var.b)
'data.frame':   3 obs. of  2 variables:
$ C1: int  1 5 9
$ C2: int  1 5 9

如果有人能对此有所了解,我将不胜感激。

【问题讨论】:

    标签: r


    【解决方案1】:

    一个是数字模式,另一个是整数模式。您可以通过以下方式查看:

    str(var.a); str(var.b)
    
    
    > str(var.a); str(var.b)
    'data.frame':   3 obs. of  2 variables:
     $ C1: num  1 5 9
     $ C2: num  1 5 9
    'data.frame':   3 obs. of  2 variables:
     $ C1: int  1 5 9
     $ C2: int  1 5 9
    

    【讨论】:

    • 没错,但这不是 all.equal 失败的原因。在重现问题并使其更加有意识时,我忘记了包括这一点。它现在捆绑在原始问题中。
    【解决方案2】:

    (我不太清楚你认为你发现了什么错误。数据框的创建方式不同。) var.a 和 var.b 的结构有两个不同:列中的元素:“var.a”中的numeric 和“var.b”中的integer;以及行名的模式:integer for 'var.a' and character in 'var.b':

    > dput(var.b)
    structure(list(C1 = c(1L, 5L, 9L), C2 = c(1L, 5L, 9L)), .Names = c("C1", 
    "C2"), row.names = c(1L, 5L, 9L), class = "data.frame")
    > dput(var.a)
    structure(list(C1 = c(1, 5, 9), C2 = c(1, 5, 9)), .Names = c("C1", 
    "C2"), row.names = c("1", "5", "9"), class = "data.frame")
    
    > mode(attr(var.b, "row.names"))
    [1] "numeric"
    > storage.mode(attr(var.b, "row.names"))
    [1] "integer"
    > mode(attr(var.a, "row.names"))
    [1] "character"
    

    补充说明:如果您想检查数值是否相等,您应该使用“check.attributes”开关:

    > all.equal(var.a, var.b, check.attributes=FALSE)
    [1] TRUE
    

    如果您查看var.bdput,您可以看到行名是数字:

    > dput(var.b)
    structure(list(C1 = c(1L, 5L, 9L), C2 = c(1L, 5L, 9L)), .Names = c("C1", 
    "C2"), row.names = c(1L, 5L, 9L), class = "data.frame")
    

    【讨论】:

    • +10 -- row.names 的帮助对字符/整数的变化非常清楚。
    • 就是这样。谢谢。帮助解释得很好,虽然不是最直观的。
    【解决方案3】:

    然而,

    typeof(rownames(var.a)) == typeof(rownames(var.b))

    返回 TRUE,这让我很困惑。

    除了投票最多的答案,请注意属性存储为"character" 用于var.a"numeric" 用于var.b

    > attr(var.a, "row.names")
    [1] "1" "5" "9"
    > attr(var.b, "row.names")
    [1] 1 5 9
    

    rownames() 函数会将其输出值强制转换为"character"

    > rownames(var.a)
    [1] "1" "5" "9"
    > rownames(var.b)
    [1] "1" "5" "9"
    

    这就是你在上面的命令中得到TRUE 的原因。根据?rownames

    对于数据框,rownames 的值应该是非重复和非缺失名称的字符向量(这是强制的),而 colnames 的值应该是(最好)唯一的语法有效名称的字符向量。在这两种情况下,value 都会被 as.character 强制转换,设置 colnames 会将行名转换为字符。

    更相关的检查是:

    > typeof(attr(var.a, "row.names")) == typeof(attr(var.b, "row.names"))
    [1] FALSE
    

    这就是说,我相信all.equal() 消息充其量是神秘的......

    【讨论】:

      猜你喜欢
      • 2013-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-18
      • 2013-10-11
      • 2019-12-22
      • 2012-01-21
      • 2018-12-31
      相关资源
      最近更新 更多