R all.equal中可能存在的错误

时间:2012-09-17 05:13:20

标签: r

我在R的all.equal函数中遇到了一些奇怪的行为。基本上,我以不同方式创建两个相同的data.frames,然后调用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的rownames(一旦它们成为一个字符,另一次是数字向量)。 all.equall函数的响应:

  

[1]“属性:&lt;组件2:模式:字符,数字&gt;”
  [2]“属性:&lt;组件2:目标是字符,当前是   数字&gt;“

然而,

  

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

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

3 个答案:

答案 0 :(得分:11)

(我不清楚你认为你发现了什么错误。数据框架的创建方式不同。)var.a和var.b的结构有两个不同之处:列中的元素:'var.a'中的numeric和'var.b'中的integer;和rownames的模式:'integer代表'var.a'和character代表'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.b查看dput,则可以看到rownames是数字:

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

答案 1 :(得分:1)

  

然而,

     

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的原因。根据{{​​1}}:

  

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

更相关的检查是:

?rownames

这就是说,我认为> typeof(attr(var.a, "row.names")) == typeof(attr(var.b, "row.names")) [1] FALSE 信息充其量是神秘的......

答案 2 :(得分:0)

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

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