ho qualche codice R che assomiglia a questo:codice Refactor R quando le funzioni di libreria uso non standard di valutazione
library(dplyr)
library(datasets)
iris %.% group_by(Species) %.% filter(rank(Petal.Length, ties.method = 'random')<=2) %.% ungroup()
Dare:
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
Questa gruppi di specie, e per ogni gruppo mantiene solo i due con il Petal.Length più corto. Ho alcune duplicazioni nel mio codice, perché lo faccio più volte per colonne e numeri diversi. Es .:
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()
Voglio estrarre questo in una funzione. L'approccio naive non funziona:
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
quanto mi risulta, l'espressione rank(Petal.Length, ties.method = 'random') <= 2
viene valutata in un contesto diverso, introdotto dalla funzione filter
, che fornisce un significato per il Petal.Length
espressione. Non posso semplicemente scambiare una variabile per Petal.Length, perché verrà valutata nel contesto sbagliato. Ho provato a utilizzare diverse combinazioni di substitute
e eval
, dopo aver letto questa pagina: Non-standard evaluation. Non riesco a capire una combinazione appropriata. Penso che il problema potrebbe essere che non voglio solo passare attraverso un'espressione dal chiamante (Petal.Length
) a filter
per valutarlo - Voglio costruire una nuova espressione più grande (rank(Petal.Length, ties.method = 'random') <= 2
) e poi passare l'intera espressione attraverso a filter
da valutare.
- Come posso refactoring questo espressione in una funzione?
- Più in generale, come devo fare per estrarre un'espressione R in una funzione?
- Ancora più in generale, mi sto avvicinando a questo con la mentalità sbagliata? In più lingue mainstream con cui ho familiarità (ad es. Python, C++, C#), questa è un'operazione relativamente semplice che voglio fare sempre per rimuovere la duplicazione nel mio codice. In R sembra (almeno per me) che la valutazione non standard possa renderla un'operazione non ovvia. Dovrei fare qualcos'altro interamente?
http: // adv-r. had.co.nz/Computing-on-the-language.html – James
Credo che hadley stia lavorando a questo con il pacchetto lazyeval, che fornirebbe la struttura generale per implementare versioni standard delle funzioni NSE in altri pacchetti. – baptiste