2012-05-20 11 views
17

Utknąłem z małym problemem R z data.table. Twoja pomoc jest bardzo ceniona. Jak to zrobić:W R data.table, w jaki sposób przekazać zmienne parametry do wyrażenia?

getResult <- function(dt, expr, gby) { 
    e <- substitute(expr) 
    b <- substitute(gby) 
    return(dt[,eval(e),by=b]) 
} 

v1 <- "Sepal.Length" 
v2 <- "Species" 

dt <- data.table(iris) 
rDT <- getResult(dt, sum(v1, na.rm=TRUE), v2) 

dostaję następujący błąd:

Error in sum(v1, na.rm = TRUE) : invalid 'type' (character) of argument

Teraz zarówno v1 i v2 przejdzie z innego programu jako zmienna znaków, więc nie mogę zrobić tego v1<- quote(Sepal.Length) co wydaje się praca.

+9

To może postawić cię na właściwej drodze: 'dt [, sum (get (v1), na.rm = TRUE), by = v2]' lub zaproponuj alternatywne podejście, jeśli jesteś elastyczny. – flodel

+0

Thx. Udało się, co się stało? Funkcja pobiera obiekt o nazwie v1. Co funkcja zastępcza zrobiła dla tego wyrażenia? Czy to nic nie dało i próbowało zastąpić v1 wartością znaku "Sepal.Length"? – user1157129

Odpowiedz

20

alternatywą dla flodel za odpowiedź w komentarzach może być

e <- parse(text = paste0("sum(", v1, ", na.rm = TRUE)")) 

b <- parse(text = v2) 

rDT2 <- dt[, eval(e), by = eval(b)] 

#    b V1 
# [1,]  setosa 250.3 
# [2,] versicolor 296.8 
# [3,] virginica 329.4 

EDIT:

I umieścić to do funkcji,

getResult <- function(dt, expr, gby){ 
    return(dt[, eval(expr), by = eval(gby)]) 
} 

(dtR <- getResult(dt = dt, expr = e, gby = b)) 
# gives the same result as above 


EDIT od Mateusza : Istnieje subtelny powód, dla którego metody mogą być w niektórych przypadkach szybsze niż i eval \ quote. Jednym z powodów, dla których grupowanie może być szybkie, jest to, że data.table sprawdza j, aby zobaczyć, z których kolumn korzysta, a następnie rozdziela tylko te używane kolumny (FAQ 1.12 i 3.1). Do tego celu używa on base::all.vars(j). Podczas korzystania get() w j kolumna używana jest ukryte przed all.vars i data.table wraca do podzbioru wszystkie kolumny na wszelki wypadek wyrażenie j potrzebuje ich (podobnie jak przy .SD symbol jest używany w j, dla których .SDcols dodano do rozwiązania) . Jeśli mimo to wszystkie kolumny są używane, to nie robi to różnicy, ale jeśli DT mówi 1e7x100, zgrupowane j=sum(V1) powinny być znacznie szybsze niż zgrupowane j=sum(get("V1")) z tego powodu. Przynajmniej tak powinno się stać, a jeśli nie, to może to być błąd. Jeśli z drugiej strony wiele zapytań jest konstruowanych dynamicznie i powtarzalnie, może przyjść do nich czas na paste0 i parse. Wszystko zależy naprawdę. Ustawienie verbose=TRUE powinno wydrukować komunikat o wykrytych kolumnach używanych przez j, aby można było to sprawdzić.

+0

Dzięki, wracając do pierwotnego pytania, jak mam to zrobić z rozwiązaniem getResult <- function (dt, expr, gby) { print (dt [, eval (wyrażenie), przez = eval (b)]) } v1 <- "Sepal.Length" v2 <- "Gatunek" e <- pars (text = wklej ("sum (", v1, ", na.rm = TRUE)")) b <- pars (text = v2) # rDT2 <- dt [, eval (e), przez = eval (b)] dtR <- getResult (dt, e, b) – user1157129

+0

@ user1157129, Przepraszamy za pominięcie funkcji zgodnie z wymaganiami Twoje pytanie. Zobacz edycję sugestii. – BenBarnes

+0

Przepraszam, Ben, nie działa, czy coś zbieram? getResult <- function (dt, expr, gby) { return (dt [, eval (wyraż), przez = eval (gby)]) } dt <- data.table (iris) v1 <- "Sepal.Length" v2 <- "Gatunek" e <- pars (text = wklej ("sum (", v1, ", na.rm = TRUE)")) b <- parse (text = v2) dtR <- getResult (dt = dt, expr = e, gby = b) – user1157129

Powiązane problemy