25

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

na.rm = TRUE每当它是一个选项时,我如何要求 R 进行设置?我发现

options(na.action = na.omit)

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

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

但这不是我要找的。我想知道是否有什么我可以在全球/普遍范围内做的事情,而不是为每个功能做这件事。

4

4 回答 4

12

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

  1. 列出所有na.rm作为参数的函数。在这里,我将搜索限制在基本包中。
  2. 获取每个函数并在其主体的开头添加这一行:na.rm = TRUE
  3. 将功能分配回基本包。

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" 

然后对于我更改正文的每个函数,代码的灵感来自包(FAQ 2.23),它在anddata.table的开头添加了一行。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
于 2013-07-02T10:20:22.527 回答
9

无法更改na.rmTRUE全局。(请参阅问题下的 Hong Ooi 的评论。)

编辑:

不幸的是,您不想要的答案是唯一普遍有效的答案。没有像 na.action 那样的全局选项,它只影响 lm、glm 等建模函数(即使在那里,也不能保证在所有情况下都有效)。– Hong Ooi 2013 年 7 月 2 日在 6:23

于 2013-07-31T23:39:15.630 回答
6

对于我的 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))也有效。


您还可以将其设为全局选项:

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

现在您可以使用 设置默认值options(),例如options(na.rm = TRUE)

于 2017-06-09T09:22:07.933 回答
4

已经有几个关于na.rm在全球范围内改变论点的答案。我只想注意partial()来自purrrpryr包的功能。使用此函数,您可以使用预定义的参数创建现有函数的副本:

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

要覆盖函数,只需删除点“。” 从 lapply 电话。受此博文启发

于 2019-03-28T21:56:23.287 回答