我有一个包含因子的数据帧。当我使用子集或其他索引函数创建这个数据帧的子集时,就创建了一个新的数据帧。然而,因子变量保留其所有原始水平,即使它们不存在于新的数据框架中。

这在绘制面图或使用依赖于因子级别的函数时会导致问题。

在新的数据框架中从一个因子中移除级别最简洁的方法是什么?

这里有一个例子:

df <- data.frame(letters=letters[1:5],
                    numbers=seq(1:5))

levels(df$letters)
## [1] "a" "b" "c" "d" "e"

subdf <- subset(df, numbers <= 3)
##   letters numbers
## 1       a       1
## 2       b       2
## 3       c       3    

# all levels are still there!
levels(subdf$letters)
## [1] "a" "b" "c" "d" "e"

当前回答

这里有一种方法

varFactor <- factor(letters[1:15])
varFactor <- varFactor[1:5]
varFactor <- varFactor[drop=T]

其他回答

这是令人讨厌的。我通常是这样做的,以避免加载其他包:

levels(subdf$letters)<-c("a","b","c",NA,NA)

这就得到了:

> subdf$letters
[1] a b c
Levels: a b c

注意,新级别将取代旧级别中占据其索引的任何内容(subdf$letters),因此如下所示:

levels(subdf$letters)<-c(NA,"a","c",NA,"b")

不能工作。

当你有很多关卡时,这显然不太理想,但对于少数关卡来说,这是快速而简单的。

另一种方法,但使用dplyr

library(dplyr)
subdf <- df %>% filter(numbers <= 3) %>% droplevels()
str(subdf)

编辑:

同样有效!感谢agenis

subdf <- df %>% filter(numbers <= 3) %>% droplevels
levels(subdf$letters)

为了完整起见,现在在forcats包http://forcats.tidyverse.org/reference/fct_drop.html中也有fct_drop。

它与液滴处理NA的方式不同:

f <- factor(c("a", "b", NA), exclude = NULL)

droplevels(f)
# [1] a    b    <NA>
# Levels: a b <NA>

forcats::fct_drop(f)
# [1] a    b    <NA>
# Levels: a b

已经尝试了这里的大多数例子,如果不是全部,但似乎没有一个在我的情况下工作。 经过相当一段时间的斗争,我尝试使用as.character()在因子列上将其更改为带有字符串的col,这似乎工作得很好。

不确定性能问题。

如果你不想要这种行为,不要使用因子,而是使用字符向量。我觉得这比事后修补要好得多。在用read加载数据之前,请尝试以下操作。表或read.csv:

options(stringsAsFactors = FALSE)

缺点是你只能按字母排序。(重新排序是你的朋友情节)