Wie übergebe ich in R data.table variable Parameter an einen Ausdruck?
-
12-12-2019 - |
Frage
Ich habe ein kleines R-Problem mit data.table
.Deine Hilfe ist sehr Willkommen.Wie mache ich das:
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)
Ich erhalte folgende Fehlermeldung:
Fehler in sum(v1, na.rm = TRUE):Ungültiger 'Typ' (Zeichen) von Argument
Nun, beides v1
Und v2
von einem anderen Programm als Zeichenvariable übergeben werden, daher kann ich das nicht tun v1<- quote(Sepal.Length)
was zu funktionieren scheint.
Lösung
Eine Alternative zu Flodels Antwort in den Kommentaren könnte sein
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
BEARBEITEN:
Und um dies in eine Funktion zu bringen,
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 von Matthew:Es gibt einen subtilen Grund dafür paste0
Und eval
\ quote
Methoden können schneller sein als get
in manchen Fällen auch.Einer der Gründe, warum die Gruppierung schnell erfolgen kann, ist dieser data.table
inspiziert j
Um zu sehen, welche Spalten verwendet werden, werden nur Teilmengen dieser verwendeten Spalten erstellt (FAQ 1.12 und 3.1).Es benutzt base::all.vars(j)
das zu tun.Beim Benutzen get()
In j
Die verwendete Spalte ist ausgeblendet all.vars
Und data.table
greift für alle Fälle auf die Unterteilung aller Spalten zurück j
Ausdruck braucht sie (ähnlich wie wenn der .SD
Symbol wird in verwendet j
, wofür .SDcols
wurde zur Lösung hinzugefügt).Wenn trotzdem alle Spalten verwendet werden, macht es keinen Unterschied, aber wenn DT
ist sagen wir 1e7x100 dann eine gruppierte j=sum(V1)
sollte viel schneller sein als eine gruppierte j=sum(get("V1"))
aus diesem Grund.Zumindest soll das passieren, und wenn nicht, liegt möglicherweise ein Fehler vor.Wenn andererseits viele Abfragen dynamisch erstellt und wiederholt werden, ist es an der Zeit, dies zu tun paste0
Und parse
könnte da reinkommen.Alles hängt wirklich davon ab.Einstellung verbose=TRUE
sollte eine Meldung darüber ausgeben, welche Spalten als verwendet erkannt wurden j
, damit das überprüft werden kann.