Mam niektóre kodu R, który wygląda tak:kod Refactor R gdy funkcje biblioteczne używać niestandardowych ocena
library(dplyr)
library(datasets)
iris %.% group_by(Species) %.% filter(rank(Petal.Length, ties.method = 'random')<=2) %.% ungroup()
Dawanie:
Source: local data frame [6 x 5]
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 4.3 3.0 1.1 0.1 setosa
2 4.6 3.6 1.0 0.2 setosa
3 5.0 2.3 3.3 1.0 versicolor
4 5.1 2.5 3.0 1.1 versicolor
5 4.9 2.5 4.5 1.7 virginica
6 6.0 3.0 4.8 1.8 virginica
według gatunków Te grupy, a każda grupa trzyma tylko dwa z najkrótszym Petal.Length. Mam trochę duplikacji w moim kodzie, ponieważ robię to kilka razy dla różnych kolumn i liczb. Np .:
iris %.% group_by(Species) %.% filter(rank(Petal.Length, ties.method = 'random')<=2) %.% ungroup()
iris %.% group_by(Species) %.% filter(rank(-Petal.Length, ties.method = 'random')<=2) %.% ungroup()
iris %.% group_by(Species) %.% filter(rank(Petal.Width, ties.method = 'random')<=3) %.% ungroup()
iris %.% group_by(Species) %.% filter(rank(-Petal.Width, ties.method = 'random')<=3) %.% ungroup()
Chcę to wydobyć z funkcji. Naiwne podejście nie działa:
keep_min_n_by_species <- function(expr, n) {
iris %.% group_by(Species) %.% filter(rank(expr, ties.method = 'random') <= n) %.% ungroup()
}
keep_min_n_by_species(Petal.Width, 2)
Error in filter_impl(.data, dots(...), environment()) :
object 'Petal.Width' not found
Jak rozumiem, wyrażenie rank(Petal.Length, ties.method = 'random') <= 2
jest oceniany w innym kontekście, wprowadzonej przez funkcję filter
, który zapewnia znaczenia dla wyrażenia Petal.Length
. Nie mogę po prostu zamienić zmiennej na Petal.Length, ponieważ będzie ona oceniana w niewłaściwym kontekście. Próbowałem używać różnych kombinacji substitute
i eval
, po przeczytaniu tej strony: Non-standard evaluation. Nie mogę wymyślić odpowiedniej kombinacji. Myślę, że problem może polegać na tym, że nie chcę po prostu przechodzić przez wyrażenie od dzwoniącego (Petal.Length
) do filter
, aby to ocenić - chcę skonstruować nowe, większe wyrażenie (rank(Petal.Length, ties.method = 'random') <= 2
), a następnie przekazać to całe wyrażenie przez do filter
, aby ocenić.
- Jak mogę refactor tego wyrażenia do funkcji?
- Bardziej ogólnie, w jaki sposób powinienem uzyskać wyodrębnienie wyrażenia R do funkcji?
- Jeszcze bardziej ogólnie, czy podchodzę do tego ze złym nastawieniem? W bardziej popularnych językach, które znam (np. Python, C++, C#), jest to stosunkowo prosta operacja, którą chcę wykonywać cały czas, aby usunąć duplikację w moim kodzie. W R wydaje mi się (przynajmniej dla mnie), że niestandardowa ocena może uczynić z niej bardzo nieoczywistą operację. Czy powinienem robić coś zupełnie innego?
http: // ADV-R. had.co.nz/Computing-on-the-language.html – James
Wierzę, że hadley pracuje nad tym z pakietem lazyeval, który zapewniłby ogólne ramy do implementacji standardowych wersji funkcji NSE w innych pakietach. – baptiste