我在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
如果有人能够对此有所了解,我将不胜感激。
答案 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