2015-05-03 6 views
6

Bei der Arbeit mit Datenrahmen ist es üblich, eine Teilmenge zu benötigen. Von der Verwendung der Teilmengenfunktion wird jedoch abgeraten. Das Problem mit dem folgenden Code ist, dass der Name des Datenrahmens zweimal wiederholt wird. Wenn Sie & Paste und Munge-Code kopieren, ist es leicht, versehentlich die zweite Erwähnung von ADF nicht zu ändern, die eine Katastrophe sein kann.In R subsetting ohne Verwendung von subset() und verwenden [in prägnanter Weise, um Tippfehler zu vermeiden?

adf=data.frame(a=1:10,b=11:20) 
print(adf[which(adf$a>5),]) ##alas, adf mentioned twice 
print(with(adf,adf[{a>5},])) ##alas, adf mentioned twice 
print(subset(adf,a>5)) ##alas, not supposed to use subset 

Gibt es eine Möglichkeit, das oben genannte zu schreiben, ohne adf zweimal zu erwähnen? Leider mit with() oder innerhalb(), ich kann nicht scheinen, auf adf als Ganzes zuzugreifen?

Die Teilmenge (...) Funktion könnte es leicht machen, aber sie warnen, es nicht zu benutzen:

Dies ist eine Komfortfunktion interaktiv zur bestimmungsgemäßen Verwendung. Für die Programmierung ist es besser, die Standard-Subsetting-Funktionen wie [zu verwenden, und insbesondere die nicht standardisierte Auswertung der Argument-Teilmenge kann unerwartete Konsequenzen haben.

+1

Verwendung von 'filter' aus' dplyr'. d. h. "filter (adf, a> 5)" ist ähnlich wie "subset". Wenn Sie 'data.table' verwenden. 'setDT (adf) [a> 5]' – akrun

+2

Ich bin mit @akrun hier und gestoppt mit 'data.frames' vor langer Zeit. Sobald Sie Ihren Datensatz in eine "data.table" konvertieren, wird Ihre gesamte Syntax viel kürzer. Obwohl ich nur erwähnen möchte, dass Sie hier viel zu viel Code verwenden. Du brauchst weder 'print' noch' what', nur 'adf [adf $ a> 5,]' wirst tun, was mir wiederum nicht zu verwirrend erscheint. –

+0

Wenn Sie wissen möchten, warum die Verwendung von 'subset()' nicht empfohlen wird, sehen Sie sich bitte diese SO-Frage an (http://stackoverflow.com/questions/9860090/in-r-why-is- besser als Teilmenge). – MERose

Antwort

0

Nach einigem Nachdenken, schrieb ich eine Super einfache Funktion gegeben genannt:

given=function(.,...) { with(.,...) } 

Auf diese Weise habe ich nicht den Namen des data.frame zu wiederholen. Ich fand es auch 14 Mal schneller als filter(). Siehe unten:

adf=data.frame(a=1:10,b=11:20) 
given=function(.,...) { with(.,...) } 
with(adf,adf[a>5 & b<18,]) ##adf mentioned twice :(
given(adf,.[a>5 & b<18,]) ##adf mentioned once :) 
dplyr::filter(adf,a>5,b<18) ##adf mentioned once... 
microbenchmark(with(adf,adf[a>5 & b<18,]),times=1000) 
microbenchmark(given(adf,.[a>5 & b<18,]),times=1000) 
microbenchmark(dplyr::filter(adf,a>5,b<18),times=1000) 

Mit-Micro

> adf=data.frame(a=1:10,b=11:20) 
> given=function(.,...) { with(.,...) } 
> with(adf,adf[a>5 & b<18,]) ##adf mentioned twice :(
    a b 
6 6 16 
7 7 17 
> given(adf,.[a>5 & b<18,]) ##adf mentioned once :) 
    a b 
6 6 16 
7 7 17 
> dplyr::filter(adf,a>5,b<18) ##adf mentioned once... 
    a b 
1 6 16 
2 7 17 
> microbenchmark(with(adf,adf[a>5 & b<18,]),times=1000) 
Unit: microseconds 
          expr min  lq  mean median  uq  max neval 
with(adf, adf[a > 5 & b < 18, ]) 47.897 60.441 67.59776 67.284 70.705 361.507 1000 
> microbenchmark(given(adf,.[a>5 & b<18,]),times=1000) 
Unit: microseconds 
          expr min  lq  mean median uq  max neval 
given(adf, .[a > 5 & b < 18, ]) 48.277 50.558 54.26993 51.698 56.64 272.556 1000 
> microbenchmark(dplyr::filter(adf,a>5,b<18),times=1000) 
Unit: microseconds 
           expr  min  lq  mean median  uq  max neval 
dplyr::filter(adf, a > 5, b < 18) 524.965 581.2245 748.1818 674.7375 889.7025 7341.521 1000 

Ich bemerkte, dass given() ist eigentlich schneller ein bisschen als with(), aufgrund der Länge des Variablennamens.

Die nette Sache über given, ist, dass man einige Dinge ohne Zuordnung Inline tun kann: gegeben (data.frame (a = 1: 10, b =. 11: 20), [a> 5 & b < 18 ,])

1

Als @akrun Staaten, würde ich dplyr ‚s filter Funktion:

require("dplyr") 
new <- filter(adf, a > 5) 
new 

In der Praxis, ich die subsetting Notation nicht finden ([ ]) problematisch, weil, wenn ich einen Code-Block zu kopieren, Ich benutze Suchen und Ersetzen innerhalb von RStudio, um alle Erwähnungen des Datenrahmens im ausgewählten Code zu ersetzen. Stattdessen verwende ich dplyr, weil die Notation und Syntax für neue Benutzer (und mich!) Leichter zu folgen ist, und weil die dplyr-Funktionen "eine Sache gut machen".

Verwandte Themen