4

我在 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:模式:字符,数字>”
[2]“属性:<组件2:目标是字符,当前是数字>”

然而,

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

返回TRUE,这让我很困惑。

PS:对象的结构似乎相同:

> 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

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

4

3 回答 3

12

(我不太清楚你认为你发现了什么错误。数据框的创建方式不同。) var.a 和 var.b 的结构有两个不同:列:numeric在“var.a”和integer“var.b”中;以及行名的模式: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.bwith dput,您可以看到行名是数字:

> 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")
于 2012-09-17T06:29:09.703 回答
1

然而,

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

返回TRUE,这让我感到困惑。

除了投票最多的答案外,请注意属性存储为"character"forvar.a和 as "numeric"for 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 的值应该是(最好)唯一的语法有效名称的字符向量。在这两种情况下,值都将被 as.character 强制转换,设置 colnames 会将行名转换为字符。

更相关的检查是:

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

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

于 2015-09-01T10:45:24.003 回答
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
于 2012-09-17T05:26:36.387 回答