R中有用的data.frame的一个非常意想不到的行为是将character列作为因子。如果不考虑这一点,这会导致许多问题。例如,假设以下代码:
foo=data.frame(name=c("c","a"),value=1:2)
#   name val
# 1    c   1
# 2    a   2
bar=matrix(1:6,nrow=3)
rownames(bar)=c("a","b","c")
#   [,1] [,2]
# a    1    4
# b    2    5
# c    3    6那么你对运行bar[foo$name,]有什么期望呢?它通常应该返回根据表示行'c‘和'a’的foo$name命名的bar行。但结果是不同的:
bar[foo$name,]
#   [,1] [,2]
# b    2    5
# a    1    4原因是:foo$name不是字符向量,而是整数向量。
foo$name
# [1] c a
# Levels: a c为了获得预期的行为,我手动将其转换为字符向量:
foo$name = as.character(foo$name)
bar[foo$name,]
#   [,1] [,2]
# c    3    6
# a    1    4但问题是,我们可能很容易错过执行这一点,并在我们的代码中隐藏错误。有没有更好的解决方案?
发布于 2012-10-20 05:52:38
这是一个特性,R是按照文档说明的那样工作的。这通常可以通过以下几种方式来处理:
data.frame()时使用参数stringsAsFactors = TRUE。请参阅?data.frameoptions(stringsAsFactors =FALSE)
I(....)中包装字符变量。这会将分配给数据帧组件的对象的类更改为包括"AsIs"。一般来说,这应该不是问题,因为对象继承了(在本例中) "character"类,所以应该像以前一样工作。您可以通过以下方式查看当前运行的R进程上stringsAsFactors的默认值:
> default.stringsAsFactors()
[1] TRUE该问题在范围上比data.frame()略宽,因为这也会影响read.table()。在该函数以及上面的两个选项中,您还可以通过参数colClasses告诉R变量的所有类是什么,并且R将遵守这一点,例如
> tmp <- read.table(text = '"Var1","Var2"
+ "A","B"
+ "C","C"
+ "B","D"', header = TRUE, colClasses = rep("character", 2), sep = ",")
> str(tmp)
'data.frame':   3 obs. of  2 variables:
 $ Var1: chr  "A" "C" "B"
 $ Var2: chr  "B" "C" "D"发布于 2012-10-20 12:25:29
在下面的示例数据中,作者和标题会自动转换为因子(除非您在创建数据时添加了参数stringsAsFactors = FALSE )。如果我们忘记更改默认设置,并且不想全局设置选项,该怎么办?
我在某处发现的一些代码(很可能是这样)使用sapply()来标识因子并将其转换为字符串。
dat = data.frame(title = c("title1", "title2", "title3"),
                 author = c("author1", "author2", "author3"),
                 customerID = c(1, 2, 1))
# > str(dat)
# 'data.frame': 3 obs. of  3 variables:
#   $ title     : Factor w/ 3 levels "title1","title2",..: 1 2 3
#   $ author    : Factor w/ 3 levels "author1","author2",..: 1 2 3
#   $ customerID: num  1 2 1
dat[sapply(dat, is.factor)] = lapply(dat[sapply(dat, is.factor)], 
                                 as.character)
# > str(dat)
# 'data.frame':  3 obs. of  3 variables:
#   $ title     : chr  "title1" "title2" "title3"
#   $ author    : chr  "author1" "author2" "author3"
#   $ customerID: num  1 2 1我假设这将比使用stringsAsFactors = FALSE参数重新读取数据集更快,但从未进行过测试。
https://stackoverflow.com/questions/12982896
复制相似问题