我有一个包含因子的数据帧。当我使用子集或其他索引函数创建这个数据帧的子集时,就创建了一个新的数据帧。然而,因子变量保留其所有原始水平,即使它们不存在于新的数据框架中。
这在绘制面图或使用依赖于因子级别的函数时会导致问题。
在新的数据框架中从一个因子中移除级别最简洁的方法是什么?
这里有一个例子:
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()在使用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)
一个真正的droplevels函数是collapse::fdroplevels,它比droplevels快得多,并且不执行任何不必要的匹配或数值制表。例子:
library(collapse)
library(microbenchmark)
# wlddev data supplied in collapse, iso3c is a factor
data <- fsubset(wlddev, iso3c %!in% "USA")
microbenchmark(fdroplevels(data), droplevels(data), unit = "relative")
## Unit: relative
## expr min lq mean median uq max neval cld
## fdroplevels(data) 1.0 1.00000 1.00000 1.00000 1.00000 1.00000 100 a
## droplevels(data) 30.2 29.15873 24.54175 24.86147 22.11553 14.23274 100 b