覆盖[.data.frame以默认删除未使用的因子级别

jor*_*ran 3 r subset dataframe r-factor

之前出现子集化时丢弃未使用的因子级别的问题.常见的解决方案包括通过声明尽可能使用字符向量

options(stringsAsFactors = FALSE)
Run Code Online (Sandbox Code Playgroud)

但有时候,有序因素对于绘图是必要的,在这种情况下我们可以使用便利函数droplevels来创建一个包装器subset:

subsetDrop <- function(...){droplevels(subset(...))}
Run Code Online (Sandbox Code Playgroud)

我意识到这subsetDrop主要解决了这个问题,但是在某些情况下,子集化via [更方便(而且输入更少!).

我的问题是,为了方便起见,我们可以通过覆盖[数据帧以自动降低因子水平来推动它成为R的"默认"行为.例如,Hmisc包中包含dropUnusedLevels哪些覆盖[.factor用于对单个因子进行子集化(不再需要,因为默认值[.factor似乎具有drop用于删除未使用级别的参数).我正在寻找一种类似的解决方案,它允许我使用数据帧进行子集化,[但会自动丢弃未使用的因子级别(当然,在有序因子的情况下保留顺序).

Aar*_*ica 6

我真的很想改变默认行为; 你永远不知道你使用的其他功能何时取决于通常的默认行为.我不是写了类似的功能,以您subsetDrop但是[,像

sel <- function(x, ...) droplevels(x[...])
Run Code Online (Sandbox Code Playgroud)

然后

> d <- data.frame(a=factor(LETTERS[1:5]), b=factor(letters[1:5]))
> str(d[1:2,])
'data.frame':   2 obs. of  2 variables:
 $ a: Factor w/ 5 levels "A","B","C","D",..: 1 2
 $ b: Factor w/ 5 levels "a","b","c","d",..: 1 2
> str(sel(d,1:2,))
'data.frame':   2 obs. of  2 variables:
 $ a: Factor w/ 2 levels "A","B": 1 2
 $ b: Factor w/ 2 levels "a","b": 1 2
Run Code Online (Sandbox Code Playgroud)

如果你真的想改变默认值,你可以做类似的事情

foo <- `[.data.frame`
`[.data.frame` <- function(...) droplevels(foo(...))
Run Code Online (Sandbox Code Playgroud)

但请确保您知道名称空间是如何工作的,因为这将适用于从全局名称空间调用的任何内容,但基本名称空间中的版本不会更改.这可能是一件好事,但这是你想要确保理解的东西.在此更改后,输出是您想要的.

> str(d[1:2,])
'data.frame':   2 obs. of  2 variables:
 $ a: Factor w/ 2 levels "A","B": 1 2
 $ b: Factor w/ 2 levels "a","b": 1 2
Run Code Online (Sandbox Code Playgroud)


koh*_*ske 5

你可以通过覆盖drop参数的默认值来完成这项工作,如下所示:

formals(`[.factor`)$drop <- TRUE
Run Code Online (Sandbox Code Playgroud)

UPDATE

至于data.frame,你可以通过:

`[.data.frame` <- function(...)droplevels(base::`[.data.frame`(...))
Run Code Online (Sandbox Code Playgroud)

实际上和@ Aaron的相似.

如果要取消此行为,则:

rm(`[.data.frame`)
Run Code Online (Sandbox Code Playgroud)

会这样做的.

> d <- data.frame(a=letters[1:10], b=LETTERS[1:10])
> str(d[1:5, ])
'data.frame':   5 obs. of  2 variables:
 $ a: Factor w/ 10 levels "a","b","c","d",..: 1 2 3 4 5
 $ b: Factor w/ 10 levels "A","B","C","D",..: 1 2 3 4 5
> `[.data.frame` <- function(...)droplevels(base::`[.data.frame`(...))
> str(d[1:5, ])
'data.frame':   5 obs. of  2 variables:
 $ a: Factor w/ 5 levels "a","b","c","d",..: 1 2 3 4 5
 $ b: Factor w/ 5 levels "A","B","C","D",..: 1 2 3 4 5
> rm(`[.data.frame`)
> str(d[1:5, ])
'data.frame':   5 obs. of  2 variables:
 $ a: Factor w/ 10 levels "a","b","c","d",..: 1 2 3 4 5
 $ b: Factor w/ 10 levels "A","B","C","D",..: 1 2 3 4 5
Run Code Online (Sandbox Code Playgroud)