2013-07-02 15 views
16

Per comandi come max l'opzione na.rm è impostata su FALSE per impostazione predefinita. Capisco perché questa è una buona idea in generale, ma mi piacerebbe spegnerla in modo reversibile per un po '- cioè durante una sessione.È possibile impostare na.rm su TRUE globalmente?

Come posso richiedere a R di impostare na.rm = TRUE ogni volta che si tratta di un'opzione? Ho trovato

options(na.action = na.omit) 

ma questo non funziona. So che posso impostare un'opzione na.rm=TRUE per ogni funzione che scrivo.

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

Ma questo non è quello che sto cercando. Mi chiedo se c'è qualcosa che potrei fare più globalmente/universalmente invece di farlo per ogni funzione.

+10

Sfortunatamente, la risposta che non vuoi è l'unica che funziona in generale. Non esiste un'opzione globale per questo come c'è per 'na.action', che riguarda solo le funzioni di modellazione come' lm', 'glm', etc (e anche lì, non è garantito che funzioni in tutti i casi). –

+0

@HongOoi - Penso che alla luce del numero elevato di voti positivi del tuo commento dovrebbe essere ridisegnato come risposta (o "la" risposta potenzialmente). – thelatemail

+1

Un'alternativa per avere un controllo preciso di dove/quando omettere NA potrebbe essere includere una variabile come 'do.omit.na = TRUE' all'inizio del tuo script, e usarla successivamente se applicabile con' max (x, na.rm = do.omit.na) '. – QuantIbex

risposta

10

Non è possibile cambiare na.rm a TRUE a livello globale. (Vedi il commento di Hong Ooi sotto la domanda.)

EDIT:

Purtroppo, la risposta non si desidera che è l'unico che funziona in generale. Non esiste un'opzione globale per questo come c'è per il numero , che riguarda solo le funzioni di modellazione come lm, glm, ecc. (e anche lì, non è garantito che funzioni in tutti i casi).- Hong Ooi 2 luglio '13 a 6:23

9

Una soluzione (pericoloso), è quello di effettuare le seguenti operazioni:

  1. Lista tutte le funzioni che hanno come argomento na.rm. Qui ho limitato la mia ricerca al pacchetto base.
  2. Recupera ciascuna funzione e aggiungi questa riga all'inizio del suo corpo: na.rm = TRUE
  3. Assegna la funzione al pacchetto base.

Quindi, prima devo conservare in un elenco (ll) tutte le funzioni che hanno come argomento 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 metodo migliore per ottenere le funzioni di argomenti tutti di na.rm (grazie a mnel commento)

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

Così na.rm.f lista assomiglia:

[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" 

Quindi per ogni funzione cambio il corpo, il codice è ispirato dal pacchetto data.table (Domande frequenti 2.23) che aggiunge una riga all'inizio di rbind.data.frame e 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()) 
     } 
    } 
    }) 

No se si controlla, la prima linea di ogni funzione della nostra lista:

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

'Funs <- Filtro (is.function, sapply (ls (baseenv()), get, baseenv())); na.rm.f <- nomi (Filter (function (x) any (nomi (formals (args (x)))% in% 'na.rm'), Funs)) 'raccogli' min' e 'max '.... – mnel

+0

@mnel grazie. Aggiungo il tuo suggerimento alla mia risposta – agstudy

+0

Apprezzo la risposta e penso di capire quello che stai facendo, ma non posso andare avanti o indietro perché l'ultima risposta dà "Errore in ss [[2]]: pedice fuori limite" e la prima risposta dà ' max (5, NA) = NA'. – Hugh

1

Per il mio pacchetto R, ho sovrascritto le funzioni esistenti e meansum. Grazie alla grande Ben (commenti qui sotto), ho alterato le mie funzioni a questo:

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

Dopo questo, invece di mean(c(2, NA, 3)) = 2.5NA.

E per sum:

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

Questo produrrà sum(c(2, NA, 3)) = 5 invece di NA.

sum(c(2, NA, 3, NaN)) funziona anche.

+0

forse leggermente meglio usare 'base :: mean (...)' piuttosto che 'mean.default (...)' (nel caso in cui si decida di prendere la media di qualcosa che ha un metodo diverso da quello predefinito). –

+0

Grazie! Mettimi un'altra idea :) Modificherò la mia risposta. –

Problemi correlati