Wenn ich einen data.frame filtern muss, dh Zeilen extrahieren muss, die bestimmte Bedingungen erfüllen, bevorzuge ich die subset
Funktion:
subset(airquality, Month == 8 & Temp > 90)
Anstelle der [
Funktion:
airquality[airquality$Month == 8 & airquality$Temp > 90, ]
Es gibt zwei Hauptgründe für meine Präferenz:
Ich finde, der Code liest sich besser, von links nach rechts. Sogar Leute, die nichts über R wissen, könnten sagen, was die
subset
obige Aussage tut.Da Spalten im
select
Ausdruck als Variablen bezeichnet werden können, kann ich einige Tastenanschläge speichern. In meinem obigen Beispiel musste ich nurairquality
einmal mitsubset
, aber dreimal mit tippen[
.
Also lebte ich glücklich, benutzte es subset
überall, weil es kürzer ist und besser liest, und befürwortete sogar seine Schönheit meinen R-Programmierkollegen. Aber gestern ist meine Welt auseinandergebrochen. Beim Lesen der subset
Dokumentation bemerke ich diesen Abschnitt:
Warnung
Dies ist eine praktische Funktion zur interaktiven Verwendung. Für die Programmierung ist es besser, die Standard-Teilmengenfunktionen wie [zu verwenden, und insbesondere die nicht standardmäßige Bewertung der Argument-Teilmenge kann unerwartete Konsequenzen haben.
Könnte jemand helfen zu klären, was die Autoren meinen?
Was verstehen sie unter " interaktiv nutzen "? Ich weiß, was eine interaktive Sitzung ist, im Gegensatz zu einem Skript, das im BATCH-Modus ausgeführt wird, aber ich sehe nicht, welchen Unterschied es machen sollte.
Könnten Sie dann bitte " die nicht standardmäßige Bewertung der Argumentuntermenge " erklären und warum dies gefährlich ist, vielleicht ein Beispiel geben?
with(airquality, airquality[Month == 8 & Temp > 90, ])
dplyr::filter
hat das gleiche Problem. Das heißt, wenn die Umgebung zufällig eine Variable mit diesem Namen hat, wird sie anstelle der Variablen im Datenrahmen verwendet. Verwechselt das Debuggen!Antworten:
Diese Frage wurde in den Kommentaren von @James gut beantwortet und wies auf eine ausgezeichnete Erklärung von Hadley Wickham für die Gefahren
subset
(und Funktionen wie diese) [hier] hin . Geh und lies es!Es ist eine etwas lange Lektüre, daher kann es hilfreich sein, hier das Beispiel aufzuzeichnen, das Hadley verwendet und das die Frage "Was kann schief gehen?" Am direktesten anspricht:
Hadley schlägt das folgende Beispiel vor: Angenommen, wir möchten einen Datenrahmen mit den folgenden Funktionen unterteilen und dann neu anordnen:
Dies gibt den Fehler zurück:
weil R nicht mehr "weiß", wo sich das Objekt namens "cyl" befindet. Er weist auch auf die wirklich bizarren Dinge hin, die passieren können, wenn es zufällig ein Objekt namens "Zyl" in der globalen Umgebung gibt:
(Führen Sie sie aus und überzeugen Sie sich selbst, es ist ziemlich verrückt.)
quelle
subset(mtcars, cyl == 4)
(auf oberster Ebene), wo sucht R nach Zyl? Wenn es in dasmtcars
Objekt schaut , an das übergeben wirdsubset()
, sollte es dann nicht finden können,cyl
selbst wennscramble
es sich in einer anderen Funktion befindet, damtcars
es immer noch an das Objekt übergeben wird ? Wenn meine Frage keinen Sinn ergibt, können Sie einfach näher erläutern, warum R nicht mehr finden kanncyl
. Vielen Dank!subset.data.frame
, das, was wir an diesem Punkt zu bewerten versuchen, ist einfachcondition
. Das gibt es in nichtmtcars
. Sosubset.data.frame
verwendet ,enclos = parent.frame()
um sicherzustellen , dasscondition
korrekt als ausgewertet wirdcyl == 4
. Aber dann sind wir wieder zum umschließenden Rahmen zurückgekehrt, und jetzt, wo R danach sucht, schautcyl
es nicht mehr hineinmtcars
. Wenn wir nicht verwenden würdenenclos
, würde so etwassubset(mtcars,cyl == a)
überhaupt nicht funktionieren.subset.data.frame
istx[r, vars, drop = drop]
. Das Problem ist, wie man von den nicht zitiertensubset
undselect
Argumenten zu etwas gelangt, an das man gültig übergeben kann[.data.frame
.[]
?Ist auch
[
schneller:quelle
subset
Gegensatz zu[
Zeilen, in denen der Filter ausgewertet wirdNA
. Wenn Sie dies tun, werden Sie sehen, dass beide im Vergleich "fair" genauso schnell sind:x <- do.call(rbind, rep(list(airquality), 100)); microbenchmark(subset(x, Month == 8 & Temp > 90),{ i <- x$Month == 8 & x$Temp > 90; x[!is.na(i) & i ,] })