2011-10-01 60 views
3

我使用这样的事情来筛选我的数据帧:无法过滤数据框?

d1 = data.frame(data[data$ColA == "ColACat1" & data$ColB == "ColBCat2", ]) 

当我打印d1,它按预期工作。但是,当我键入d1 $ ColB时,它仍会打印原始数据框中的所有内容。

> print(d1) 
ColA  ColB 
----------------- 
ColACat1 ColBCat2 
ColACat1 ColBCat2 

> print(d1$ColA) 
Levels: ColACat1 ColACat2 

也许这是预期,但是当我通过d1到ggplot,它搅乱了我的图形,并且不使用过滤器。是否有反正我可以过滤数据帧,并得到只有匹配过滤器的记录?我想d1不知道data的存在。

回答

5

正如你所暗示的,R中的默认行为是将数据帧中的字符列视为特殊数据类型,称为factor。这是一个功能,而不是一个错误,但是如果你不期待它并且不知道如何正确使用它,那么它就像任何有用的功能一样,这可能会让人感到困惑。

factors旨在表示分类(而不是数字或定量)变量,这些变量经常出现在统计数据中。

您使用的子集操作实际上正常工作。也就是说,他们会返回数据框的正确子集。但是,该变量的levels属性保持不变,并且仍具有全部其中的原始级别。

这意味着用R编写的任何方法都是为了利用factors而将该列视为具有一堆关卡的分类变量,其中许多关键字不存在。在统计数据中,人们通常希望追踪“缺失”的分类变量水平。

我其实更喜欢与stringsAsFactors = FALSE一起工作,但很多人对此表示不满,因为它可以减少代码的可移植性。 (TRUE是默认设置,因此与其他人分享您的代码可能会有风险,除非您以options的电话号码为每个脚本添加前缀)。

一种可能更方便的解决方案,特别是用于数据帧,是结合subsetdroplevels功能:

subsetDrop <- function(...){ 
    droplevels(subset(...)) 
} 

并使用该函数来提取数据帧的子集在被保证以除去一种方式结果中任何未使用的级别。

+0

+1非常感谢你的解释。我不明白的是,为什么ggplot最终使用了不存在的级别。可能是他们有自己的理由。我在R和ggplot中都是一个完整的初学者,所以我最终花了一个多小时的时间试图了解发生了什么:) – Legend

+1

考虑因素水平的处理(即保留它们,尽管缺少数据),例如在分面时数据世界中的'正常',但它使大多数其他人失去知觉。理由是,如果缺少某些东西,你希望明确地显示它缺失,例如通过显示一个没有数据的方面。 – joran

2

这真是太痛苦了!如果你没有这样做,ggplot会搞砸。使用此选项在我的脚本开始解决它:

options(stringsAsFactors = FALSE) 

看起来它是预期的行为,但不幸的是我已经开启此功能用于其他目的,并开始造成麻烦,我的所有其他脚本。

+0

这将解决您的问题,但默认的全局设置是stringsAsFactors = TRUE。当你构造data.frame(...,stringsAsFactors = FALSE)时,你也可以将它作为参数传递。但在你的例子中,当你构造最初的'数据'data.frame时,必须完成这个工作。 –