2015-05-03 9 views
6

Podczas pracy z ramkami danych często potrzebny jest podzbiór. Jednak korzystanie z funkcji podzbioru jest odradzane. Problem z następującym kodem polega na tym, że nazwa ramki danych jest powtarzana dwukrotnie. Jeśli skopiujesz kod & i munge, łatwo jest przypadkowo nie zmienić drugiej wzmianki o adf, która może być katastrofą.W R subsetowanie bez użycia podzbioru() i użyć [w bardziej zwięzły sposób, aby zapobiec literówek?

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 

Czy istnieje sposób, aby napisać powyższe, nie wspominając o adf dwa razy? Niestety w przypadku funkcji with() lub within() nie mogę uzyskać dostępu do adf jako całości?

Funkcja podzbiór (...) mógłby zrobić to łatwe, ale ostrzegają, aby nie używać go:

Jest to funkcja wygoda przeznaczone do użytku interaktywnie. Do programowania lepiej używać standardowych funkcji podsekcji takich jak [, a w szczególności nietypowa ocena podzbioru argumentów może mieć nieprzewidziane konsekwencje.

+1

Używanie 'filtru' z' dplyr'. tj. "filter (adf, a> 5)" jest podobne do "podzbioru". Jeśli używasz 'data.table'. 'setDT (adf) [a> 5]' – akrun

+2

Jestem tutaj z @akrun i przestałem używać 'data.frames' dawno temu. Po przekonwertowaniu zestawu danych na "data.table" cała składnia stanie się znacznie krótsza. Chociaż chcę tylko wspomnieć, że używasz tutaj zbyt wiele kodu. Nie potrzebujesz 'print' lub' which', po prostu 'adf [adf $ a> 5,]' zrobi to, co z kolei nie będzie dla mnie zbyt mylące. –

+0

Jeśli chcesz wiedzieć, dlaczego użycie 'subset()' nie jest zalecane, proszę spojrzeć [to pytanie SO] (http://stackoverflow.com/questions/9860090/in-r-why-is- lepiej niż podzbiór). – MERose

Odpowiedz

0

Po namyśle, napisałem bardzo prostą funkcję o nazwie Dane:

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

ten sposób, nie trzeba powtarzać nazwę data.frame. Odkryłem też, że jest 14 razy szybszy niż filter(). Patrz poniżej:

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) 

Korzystanie microbenchmark

> 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 

zauważyłem, że given() jest rzeczywiście odrobinę szybciej niż with(), ze względu na długość nazwy zmiennej.

Schludny rzeczą given, jest to, że można zrobić kilka rzeczy inline bez przypisania: podano (data.frame (a = 1: 10, b = 11. 20), [a> 5 & b < 18 ,])

1

Jak @akrun stanach, użyłbym dplyr „s filter funkcję:

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

W praktyce nie znajdę notacji podzbiorów ([ ]) problematyczne, ponieważ jeśli mogę skopiować blok kodu, Używam znajdowania i zamiany w RStudio, aby zastąpić wszystkie wzmianki o ramie danych w wybranym kodzie. Zamiast tego używam dplyr, ponieważ notacja i składnia są łatwiejsze do śledzenia dla nowych użytkowników (i dla mnie!), A ponieważ funkcje dplyra "robią dobrze jedną rzecz".

Powiązane problemy