是否可以在全球范围内将na.rm设置为TRUE?

时间:2013-07-02 06:17:01

标签: r na na.rm

对于max之类的命令,默认情况下将na.rm选项设置为FALSE。我理解为什么这一般是一个好主意,但我想在一段时间内可逆转地关闭它 - 即在会议期间。

如果可以选择R,我怎么能要求R设置na.rm = TRUE?我找到了

options(na.action = na.omit)

但这不起作用。我知道我可以为我写的每一个函数设置一个na.rm=TRUE选项。

my.max <- function(x) {max(x, na.rm=TRUE)}

但这不是我要找的东西。我想知道是否有一些我可以在全球/普遍做的事情,而不是为每个功能做。

4 个答案:

答案 0 :(得分:11)

一种解决方法(危险),是执行以下操作:

  1. 列出以na.rm为参数的所有函数。在这里,我将搜索限制在基础包中。
  2. 获取每个函数并在其正文的开头添加此行:na.rm = TRUE
  3. 将功能分配回基础包。
  4. 首先,我将所有以na.rm作为参数的函数存储在列表中(ll):

    uses_arg <- function(x,arg) 
      is.function(fx <- get(x)) && 
      arg %in% names(formals(fx))
    basevals <- ls(pos="package:base")      
    na.rm.f <- basevals[sapply(basevals,uses_arg,'na.rm')]
    

    编辑获取所有na.rm参数函数的更好方法(感谢mnel评论)

    Funs <- Filter(is.function,sapply(ls(baseenv()),get,baseenv()))
    na.rm.f <- names(Filter(function(x) any(names(formals(args(x)))%in% 'na.rm'),Funs))
    

    所以na.rm.f列表如下:

     [1] "all"                     "any"                     "colMeans"                "colSums"                
     [5] "is.unsorted"             "max"                     "mean.default"            "min"                    
     [9] "pmax"                    "pmax.int"                "pmin"                    "pmin.int"               
    [13] "prod"                    "range"                   "range.default"           "rowMeans"               
    [17] "rowsum.data.frame"       "rowsum.default"          "rowSums"                 "sum"                    
    [21] "Summary.data.frame"      "Summary.Date"            "Summary.difftime"        "Summary.factor"         
    [25] "Summary.numeric_version" "Summary.ordered"         "Summary.POSIXct"         "Summary.POSIXlt" 
    

    然后,对于我更改正文的每个函数,代码的灵感来自data.table包(FAQ 2.23),它在rbind.data.framecbind.data.frame的开头添加一行。

    ll <- lapply(na.rm.f,function(x)
      {
      tt <- get(x)
      ss = body(tt)
      if (class(ss)!="{") ss = as.call(c(as.name("{"), ss))
      if(length(ss) < 2) print(x)
      else{
        if (!length(grep("na.rm = TRUE",ss[[2]],fixed=TRUE))) {
          ss = ss[c(1,NA,2:length(ss))]
          ss[[2]] = parse(text="na.rm = TRUE")[[1]]
          body(tt)=ss
          (unlockBinding)(x,baseenv())
          assign(x,tt,envir=asNamespace("base"),inherits=FALSE)
          lockBinding(x,baseenv())
          }
        }
      })
    

    否,如果你检查我们列表中每个函数的第一行:

    unique(lapply(na.rm.f,function(x) body(get(x))[[2]]))
    [[1]]
    na.rm = TRUE
    

答案 1 :(得分:9)

无法在全球范围内将na.rm更改为TRUE。 (参见Hong Ooi在该问题下的评论。)

修改

  

不幸的是,你不想要的答案是唯一有效的答案   通常。没有像这样的全球选择   na.action,只影响lm,glm等建模功能   (甚至在那里,并不保证在所有情况下都能工作)。 - 洪   Ooi 2013年7月2日6:23

答案 2 :(得分:4)

对于我的R包,我覆盖了现有函数meansum。感谢伟大的Ben(下面的评论),我将我的功能改为:

mean <- function(x, ..., na.rm = TRUE) {
  base::mean(x, ..., na.rm = na.rm)
}

在此之后,mean(c(2, NA, 3)) = 2.5代替NA

对于sum

sum <- function(x, ..., na.rm = TRUE) {
  base::sum(x, ..., na.rm = na.rm)
}

这将产生sum(c(2, NA, 3)) = 5而不是NA

sum(c(2, NA, 3, NaN))也有效。

答案 3 :(得分:1)

已经有一些关于全局更改na.rm参数的答案。我只想注意到partial()purrr包中的pryr函数。使用此功能,您可以创建具有预定义参数的现有功能的副本:

library(purrr)
.mean <- partial(mean, na.rm = TRUE)

# Create sample vector
df <- c(1, 2, 3, 4, NA, 6, 7)

mean(df)
>[1] NA

.mean(df)
>[1] 3.833333

我们可以将此技巧与@agstudy答案结合起来,并使用na.rm = TRUE参数创建所有函数的副本:

library(purrr)

# Create a vector of function names https://stackoverflow.com/a/17423072/9300556
Funs <- Filter(is.function,sapply(ls(baseenv()),get,baseenv()))
na.rm.f <- names(Filter(function(x) any(names(formals(args(x)))%in% 'na.rm'),Funs))

# Create strings. Dot "." is optional
fs <- lapply(na.rm.f,
             function(x) paste0(".", x, "=partial(", x ,", na.rm = T)"))

eval(parse(text = fs)) 

因此,我们的.all中有.min.max.GlobalEnv等。您可以运行它们:

.min(df)
> [1] 1
.max(df)
> [1] 7
.all(df)
> [1] TRUE

要覆盖功能,只需删除点“”。从催促电话。 受this blogpost

的启发