首页 文章

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

提问于
浏览
3

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

options(stringsAsFactors = FALSE)

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

subsetDrop <- function(...){droplevels(subset(...))}

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

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

3 回答

  • 2

    我'd be really wary of changing the default behavior; you never know when another function you use depends on the usual default behavior. I' d代替你的 subsetDrop 写一个类似的函数,但对于 [ ,就像

    sel <- function(x, ...) droplevels(x[...])
    

    然后

    > 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
    

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

    foo <- `[.data.frame`
    `[.data.frame` <- function(...) droplevels(foo(...))
    

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

    > 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
    
  • 6

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

    formals(`[.factor`)$drop <- TRUE
    

    UPDATE

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

    `[.data.frame` <- function(...)droplevels(base::`[.data.frame`(...))
    

    实际上和@ Aaron的相似 .

    如果要取消此行为,则:

    rm(`[.data.frame`)
    

    会这样做的 .

    > 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
    
  • 5

    我认为更改默认值非常危险,请参阅我的回复here .

    大多数情况下,人们担心你不是需要降低因子水平(使你被迫拥有1个值的东西变得愚蠢)或者有更好的方法来完成你正在尝试的东西 . 自动丢弃可能产生的副作用可能比保存的几次击键更糟糕 . 此外,如果您正在进行可重复研究,那么您不应该依赖甚至允许计算机在没有您具体说明的情况下更改数据 .

相关问题