2016-09-06 5 views
3

Normalerweise frage ich mich, woher mysteriöse Fehler kommen, aber jetzt ist meine Frage, woher ein mysteriöser Mangel an Fehlern kommt.Warum Teilmenge nichts gegen fehlende Teilmenge Argument für Dataframes?

Lassen

numbers <- c(1, 2, 3) 
frame <- as.data.frame(numbers) 

Wenn ich tippe

subset(numbers,) 

(so möchte ich einige Teilmenge nehmen, aber vergessen, die Teilmenge-Argument der Teilmenge Funktion zu spezifizieren), dann R erinnert mich (wie es sollte):

Fehler in subset.default (Zahlen):
Argument "Subset" fehlt, mit kein Standard

jedoch, wenn ich schreibe

subset(frame,) 

(so die gleiche Sache mit einem data.frame anstelle eines Vektors), ist es nicht einen Fehler, sondern gibt nur die (voll) Datenrahmen.

Was geht hier vor? Warum bekomme ich nicht meine wohlverdiente Fehlermeldung?

Antwort

8

tl; dr: Die Funktion subset ruft je nach Objekttyp unterschiedliche Funktionen (unterschiedliche Methoden) auf. Im obigen Beispiel verwendet subset(numbers,)subset.default, während subset(frame,)subset.data.frame verwendet.


R hat ein paar objektorientierte Systeme eingebaut. Am einfachsten und am häufigsten wird S3 genannt. Dieser OO-Programmierstil implementiert, was Wickham eine "generische Funktion OO" nennt. Unter diesem OO-Stil betrachtet ein Objekt, das als generische Funktion bezeichnet wird, die Klasse eines Objekts und wendet dann die richtige Methode auf das Objekt an. Wenn keine direkte Methode existiert, ist immer eine Standardmethode verfügbar.

Um eine bessere Vorstellung davon zu bekommen, wie S3 funktioniert und die anderen OO-Systeme funktionieren, können Sie den relevanten Teil der Advanced R-Site auschecken. Das Verfahren zum Finden der richtigen Methode für ein Objekt wird als Methodenversand bezeichnet. Sie können mehr darüber in der Hilfedatei ?UseMethod lesen.

Wie im Abschnitt Details von ?subset, die subset Funktion "ist eine generische Funktion." Das bedeutet, dass subset die Klasse des Objekts im ersten Argument untersucht und dann mithilfe des Methodenversands die entsprechende Methode auf das Objekt anwendet.

Die Methoden einer generischen Funktion als

< generische Funktion name> kodiert. < Klassenname>

und kann unter methods(<generic function name>) gefunden werden. Für subset erhalten wir

methods(subset) 
[1] subset.data.frame subset.default subset.matrix  
see '?methods' for accessing help and source code 

, die die angibt, ob das Objekt eine Daten hat.Frame-Klasse, dann ruft die subset.data.frame die Methode (Funktion). Es ist wie folgt definiert:

subset.data.frame 
function (x, subset, select, drop = FALSE, ...) 
{ 
    r <- if (missing(subset)) 
     rep_len(TRUE, nrow(x)) 
    else { 
     e <- substitute(subset) 
     r <- eval(e, x, parent.frame()) 
     if (!is.logical(r)) 
      stop("'subset' must be logical") 
     r & !is.na(r) 
    } 
    vars <- if (missing(select)) 
     TRUE 
    else { 
     nl <- as.list(seq_along(x)) 
     names(nl) <- names(x) 
     eval(substitute(select), nl, parent.frame()) 
    } 
    x[r, vars, drop = drop] 
} 

Beachten Sie, dass, wenn die Teilmenge Argument fehlt, die ersten Zeilen

r <- if (missing(subset)) 
     rep_len(TRUE, nrow(x)) 

einen Vektor von Trues der gleichen Länge wie die data.frame erzeugen, und die letzte Linie

x[r, vars, drop = drop] 

führt diesen Vektors in die Reihe Argument, das heißt, wenn Sie nicht eine Teilmenge Argument, dann ist die subset Funktion gibt alle Zeilen der Daten enthalten sind. Rahmen.

Wie wir von der Ausgabe des methods Anrufs sehen können, hat subset keine Methoden für atomare Vektoren. Das bedeutet, wie Sie Ihre Fehler

Fehler in subset.default (Zahlen,)

, dass, wenn Sie subset auf einen Vektor anwenden, R ruft die subset.default Methode, die als

subset.default 
function (x, subset, ...) 
{ 
    if (!is.logical(subset)) 
     stop("'subset' must be logical") 
    x[subset & !is.na(subset)] 
} 
definiert ist

Die Funktion subset.default löst einen Fehler mit stop aus, wenn das Teilmengenargument fehlt.