2013-07-02 17 views
16

Für Befehle wie max ist die Option na.rm standardmäßig auf FALSE eingestellt. Ich verstehe, warum dies im Allgemeinen eine gute Idee ist, aber ich würde es gerne für eine Weile reversibel abstellen - zum Beispiel während einer Sitzung.Ist es möglich, na.rm global auf TRUE zu setzen?

Wie kann ich verlangen, dass R na.rm = TRUE immer dann einstellt, wenn es eine Option ist? Ich fand

options(na.action = na.omit) 

aber das funktioniert nicht. Ich weiß, dass ich eine na.rm=TRUE Option für jede Funktion, die ich schreibe, festlegen kann.

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

Aber das ist nicht, was ich suche. Ich frage mich, ob es etwas gibt, das ich globaler/universeller machen könnte, anstatt es für jede Funktion zu tun.

+10

Leider ist die Antwort, die Sie nicht wollen, die einzige, die allgemein funktioniert. Es gibt keine globale Option dafür, wie es für "na.action" gilt, was nur Modellierungsfunktionen wie "lm", "glm" usw. betrifft (und selbst dort wird nicht garantiert, dass es in allen Fällen funktioniert). –

+0

@HongOoi - Ich denke, angesichts der großen Anzahl von Upvotes auf Ihren Kommentar sollte es als Antwort (oder "die" mögliche Antwort) aufgefrischt werden. – thelatemail

+1

Eine Alternative, um eine genaue Kontrolle darüber zu haben, wo/wann man NAS weglassen sollte, könnte sein, am Anfang des Skripts eine Variable wie 'do.omit.na = TRUE' einzufügen und sie danach mit max zu verwenden (x, na.rm = do.omit.na) '. – QuantIbex

Antwort

10

Es ist nicht möglich na.rm zu TRUE global zu ändern. (Siehe Hong Ooi Kommentar unter der Frage.)

EDIT:

Leider ist die Antwort, die Sie nicht wollen, ist der einzige, der im Allgemeinen funktioniert. Es gibt keine globale Option dafür, wie es für na.action gibt, die nur Modellierungsfunktionen wie lm, glm, etc. betrifft (und sogar dort, es ist nicht garantiert, in allen Fällen zu arbeiten).- Hong Ooi 2. Juli '13 bei 6:23

9

Eine Abhilfe (gefährlich), ist folgendes zu tun:

  1. Liste aller Funktionen, die na.rm als Argument haben. Hier habe ich meine Suche auf das Basispaket beschränkt.
  2. Holen Sie jede Funktion und fügen Sie diese Zeile am Anfang ihres Körpers: na.rm = TRUE
  3. Weisen Sie die Funktion zurück zum Basispaket.

Also zuerst speichere ich in einer Liste (ll) alle Funktionen na.rm als Argument haben:

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 bessere Methode, um alle na.rm Argument Funktionen zu erhalten (dank Kommentar 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)) 

So na.rm.f Liste wie folgt aussieht:

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

Dann für jede Funktion ändere ich den Körper, der Code ist inspiriert von data.table Paket (FAQ 2.23), die eine Zeile an den Anfang von rbind.data.frame und cbind.data.frame hinzufügen.

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

Nein, wenn Sie die erste Zeile jeder Funktion unserer Liste überprüfen,:

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

'Funs <- Filter (is.function, sapply (ls (baseenv()), get, baseenv())); na.rm.f <- Namen (Filter (Funktion (x) any (Namen (formals (args (x)))% in% 'na.rm'), Funs)) 'wird' min' und 'max '.... – mnel

+0

@Mnel danke. Ich füge deinen Vorschlag meiner Antwort hinzu. – agstudy

+0

Ich schätze die Antwort und ich denke, ich verstehe, was Sie tun, aber ich kann nicht upvote oder akzeptieren, weil die letzte Antwort gibt Fehler in ss [[2]]: Index außerhalb der Grenzen und die erste Antwort gibt ' max (5, NA) = NA'. – Hugh

1

Für meine R-Paket, überschrieb ich die vorhandenen Funktionen mean und sum. Dank der großen Ben (Kommentare unten), veränderte ich meine Funktionen dazu:

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

Nach diesem mean(c(2, NA, 3)) = 2.5 statt NA.

Und für sum:

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

Dies wird sum(c(2, NA, 3)) = 5 statt NA ergeben.

sum(c(2, NA, 3, NaN)) funktioniert auch.

+0

vielleicht etwas besser zu verwenden 'base :: mean (...)' anstatt 'mean.default (...)' (für den Fall, dass Sie den Mittelwert von etwas wählen, das eine andere als die Standardmethode hat). –

+0

Danke! Setzen Sie mich auf eine andere Idee :) Ich werde meine Antwort bearbeiten. –