Можно ли установить na.rm в TRUE глобально?

Для команд типа 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)}

Но это не то, что я ищу. Мне интересно, есть ли что-то, что я мог бы сделать более глобально/универсально, вместо того, чтобы делать это для каждой функции.

Ответы

Ответ 1

Невозможно изменить na.rm на TRUE глобально. (См. Комментарий Hong Ooi по этому вопросу.)

EDIT:

К сожалению, ответ, который вы не хотите, является единственным, который работает в общем. Там нет глобального варианта для этого, как для na.action, которая влияет только на функции моделирования, такие как lm, glm и т.д. (и даже там, во всех случаях не гарантируется работа). - Хонг Ooi Jul 2 '13 в 6:23

Ответ 2

Один способ обхода (опасный) заключается в следующем:

  • Список всех функций, имеющих na.rm в качестве аргумента. Здесь я ограничил свой поиск базовым пакетом.
  • Извлеките каждую функцию и добавьте эту строку в начало ее тела: na.rm = TRUE
  • Назначьте функцию обратно в базовый пакет.

Итак, сначала я храню в списке (11) все функции, имеющие na.rm в качестве аргумента:

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.frame и cbind.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

Ответ 3

Для моего пакета R я перезаписал существующие функции mean и sum. Благодаря великому Бену (комментарии ниже), я изменил свои функции:

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)) также работает.

Ответ 4

Было несколько ответов об изменении аргумента na.rm глобальном масштабе. Я просто хочу заметить о функции purrr 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)) 

Итак, теперь в нашем .GlobalEnv есть .all, .min, .max и т.д. Вы можете запустить их:

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

Чтобы перезаписать функции, просто удалите точку "." от радостного звонка. Вдохновленный этим постом