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

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

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

这里有一个例子:

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"

当前回答

谢谢你提出这个问题。然而,以上的解决方案都不适合我。我为这个问题做了一个变通方案,分享它以防其他人偶然发现这个问题:

对于所有包含值为零的级别的因子列,您可以先将这些列转换为字符类型,然后再将它们转换回因子。

对于上面的问题,只需添加以下代码行:

# Convert into character
subdf$letters = as.character(subdf$letters)

# Convert back into factor
subdf$letters = as.factor(subdf$letters)

# Verify the levels in the subset
levels(subdf$letters)

其他回答

非常有趣的话题,我特别喜欢因子子选择的想法。我以前遇到过类似的问题,我只是转换成字符,然后再转换回因子。

   df <- data.frame(letters=letters[1:5],numbers=seq(1:5))
   levels(df$letters)
   ## [1] "a" "b" "c" "d" "e"
   subdf <- df[df$numbers <= 3]
   subdf$letters<-factor(as.character(subdf$letters))

不幸的是,factor()在使用RevoScaleR的rxDataStep时似乎不起作用。我分两步做: 1)转换为字符并存储在临时外部数据帧(.xdf)。 2)转换回因子并存储在确定的外部数据帧中。这消除了任何未使用的因子级别,而无需将所有数据加载到内存中。

# Step 1) Converts to character, in temporary xdf file:
rxDataStep(inData = "input.xdf", outFile = "temp.xdf", transforms = list(VAR_X = as.character(VAR_X)), overwrite = T)
# Step 2) Converts back to factor:
rxDataStep(inData = "temp.xdf", outFile = "output.xdf", transforms = list(VAR_X = as.factor(VAR_X)), overwrite = T)

这里有一种方法

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

为了完整起见,现在在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,这似乎工作得很好。

不确定性能问题。