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

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

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

这里有一个例子:

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"

当前回答

你所要做的就是在子集设置后再次应用factor()到你的变量:

> subdf$letters
[1] a b c
Levels: a b c d e
subdf$letters <- factor(subdf$letters)
> subdf$letters
[1] a b c
Levels: a b c

EDIT

因子页的例子如下:

factor(ff)      # drops the levels that do not occur

要从数据框架中的所有因子列中删除级别,您可以使用:

subdf <- subset(df, numbers <= 3)
subdf[] <- lapply(subdf, function(x) if(is.factor(x)) factor(x) else x)

其他回答

我写了效用函数来做这个。现在我知道了gdata的drop。水平,看起来很相似。他们在这里(从这里):

present_levels <- function(x) intersect(levels(x), x)

trim_levels <- function(...) UseMethod("trim_levels")

trim_levels.factor <- function(x)  factor(x, levels=present_levels(x))

trim_levels.data.frame <- function(x) {
  for (n in names(x))
    if (is.factor(x[,n]))
      x[,n] = trim_levels(x[,n])
  x
}

这是一个已知的问题,您的示例所在的gdata包中的drop.levels()提供了一个可能的补救措施

> drop.levels(subdf)
  letters numbers
1       a       1
2       b       2
3       c       3
> levels(drop.levels(subdf)$letters)
[1] "a" "b" "c"

在Hmisc包中还有一个dropUnusedLevels函数。但是,它只能通过修改子集操作符[来工作,在这里不适用。

因此,基于每列的直接方法是简单的As .factor(As .character(data)):

> levels(subdf$letters)
[1] "a" "b" "c" "d" "e"
> subdf$letters <- as.factor(as.character(subdf$letters))
> levels(subdf$letters)
[1] "a" "b" "c"

为了完整起见,现在在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

从R版本2.12开始,就有了一个droplevels()函数。

levels(droplevels(subdf$letters))

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

不确定性能问题。