我不知道是否有其他人认为R中的因素非常奇怪并且应该表现得不同,但无论如何,这是问题所在:
问题
> a = matrix(rnorm(12), nrow=3, dimnames=list(LETTERS[5:7],LETTERS[1:4]))
> b = c("B","C")
> a[,b]
B C
E -1.1886578 2.6433882
F -0.9113276 0.8333795
G 1.1922121 -1.9239478
如果我使用a
索引b
,一切都按预期工作。但是,如果b
是一个因素,则其整数值用于索引:
> a[,as.factor(b)]
A B
E 0.4137923 -1.1886578
F -0.4302323 -0.9113276
G 1.2566591 1.1922121
这是我遇到的无数问题的根源,特别是因为character
经常自动转换为factor
s,例如将它们放入data.frame
。
如果这种转化发生一次并且您没有想到它,那么您就有难以追踪的错误。
可能吗?溶液
全球设置stringsAsFactors=F
可能是一种糟糕的方法,因为它可能会破坏现有代码。
相反,我每次尝试使用因子索引任何内容时,我都希望R抛出一个错误。我的想法是在我的~/.Rprofile
中添加类似下面的代码:
`[` = function(X, ...) {
if (any(is.factor(...)))
stop("Indexing with factor")
else
.Primitive("[")(X, ...)
}
以上不起作用。我似乎无法找到一个好的解决方案,除了用因子索引时,不会以任何方式中断[
。
有什么想法吗?
答案 0 :(得分:2)
您可以轻松地为data.frames执行此操作,因为存在现有的S3方法:
trace("[.data.frame", quote(if (is.factor(j)) warning("Indexing with factor")))
#you could overwrite the method instead of using trace
a = matrix(rnorm(12), nrow=3, dimnames=list(LETTERS[5:7],LETTERS[1:4]))
b = c("B","C")
as.data.frame(a)[,b]
#Tracing `[.data.frame`(as.data.frame(a), , b) on entry
# B C
#E 0.2539326 1.3292468
#F -0.4088534 -0.7554019
#G -1.2535690 0.3149922
as.data.frame(a)[,factor(b)]
#Tracing `[.data.frame`(as.data.frame(a), , factor(b)) on entry
# A B
#E -0.6147412 0.2539326
#F -0.6899518 -0.4088534
#G 1.3720187 -1.2535690
#Warning message:
# In eval(expr, envir, enclos) : Indexing with factor
untrace("[.data.frame")
您需要对[<-.data.frame
执行相同操作。
但是,我不能提供矩阵子集的解决方案,因为它是由原语处理的,我不认为你可以/应该定义一个方法。就个人而言,我很少用字符对矩阵进行子集化。
答案 1 :(得分:0)
如果b
是一个因素,只需将as.character()
包裹起来。
a[,as.character(factor(b))]
B C
E 2.0451415 0.477410
F -0.4739111 1.616437
G -0.2422863 1.791818
这些数字与你的不同,因为你没有给我们一个可重复的例子。您可以使用set.seed()
使其在将来重现。