【问题标题】:Is it possible to set na.rm to TRUE globally?是否可以将 na.rm 全局设置为 TRUE?
【发布时间】:2013-06-29 09:51:12
【问题描述】:

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

我如何要求 R 设置 na.rm = TRUE ,只要它是一个选项?我找到了

options(na.action = na.omit)

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

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

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

【问题讨论】:

  • 不幸的是,您不想要的答案是唯一普遍有效的答案。没有像na.action 那样的全局选项,它只影响lmglm 等建模函数(即使在那里,也不能保证在所有情况下都有效)。
  • @HongOoi - 我认为鉴于您的评论有大量的赞成票,它应该被重新散列为答案(或“可能的”答案)。
  • 另一种方法可以很好地控制何时/何时省略 NA,可以在脚本开头包含一个变量,例如 do.omit.na = TRUE,然后在适用时与 @987654332 一起使用它@.
  • 有人愿意详细说明为什么设置na.rm=F 是一个好主意吗?就像向自己表明您计算的 sum/mean/etc 可能不是您想要的那样的一种方式?

标签: r na na.rm


【解决方案1】:

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

  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')]

EDIT 更好的方法来获取所有 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

【讨论】:

  • Funs &lt;- Filter(is.function,sapply(ls(baseenv()),get,baseenv())); na.rm.f &lt;- names(Filter(function(x) any(names(formals(args(x)))%in% 'na.rm'),Funs)) 将收集minmax ....
  • 感谢您的回答,我想我理解您在做什么,但我不能投票或接受,因为最新的答案是Error in ss[[2]] : subscript out of bounds,而第一个答案是max(5, NA) = NA。跨度>
  • @Hugh 我编辑了我的答案。现在你没有错误。但是,不幸的是,该代码不适用于具有 na.rm 参数的 primitive 函数:"all" "any" "max" "min" "prod" "range" "sum"
  • 或者您可以将其与Defaults 包中的setDefaults 结合使用
  • @Ben Package ‘Defaults’ was removed from the CRAN repository (...) at the request of the maintainer, who had not updated it for R 3.1.0. cran.r-project.org/web/packages/Defaults/index.html
【解决方案2】:

无法将na.rm 全局更改为TRUE。 (请参阅问题下方的 Hong Ooi 的评论。)

编辑:

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

【讨论】:

    【解决方案3】:

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

    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).

    【讨论】:

    • 使用base::mean(...) 比使用mean.default(...) 可能稍微好一些(如果您决定采用非默认方法的平均值)。
    • 谢谢!让我有另一个想法:) 我会编辑我的答案。
    【解决方案4】:

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

    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)) 
    

    所以现在,我们的.GlobalEnv 中有.all.min.max 等。你可以运行它们:

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

    要覆盖函数,只需删除点“。”从 lapply 电话。 灵感来自this blogpost

    【讨论】:

      猜你喜欢
      • 2014-10-19
      • 1970-01-01
      • 1970-01-01
      • 2013-04-22
      • 1970-01-01
      • 2017-09-04
      • 1970-01-01
      • 2017-03-10
      • 2016-04-16
      相关资源
      最近更新 更多