Question

Je suis coincé avec un petit problème R avec data.table.Votre aide est très appréciée.Comment puis-je faire cela:

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)

J'obtiens l'erreur suivante :

Erreur dans sum(v1, na.rm = TRUE) :«Type» invalide (caractère) de l'argument

Maintenant, les deux v1 et v2 être transmis par un autre programme en tant que variable de caractère, donc je ne peux pas faire ça v1<- quote(Sepal.Length) ce qui semble fonctionner.

Était-ce utile?

La solution

Une alternative à la réponse de Flodel dans les commentaires pourrait être

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

MODIFIER:

Et pour mettre cela en fonction,

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 de Matthieu :Il y a une raison subtile pour laquelle paste0 et eval \ quote les méthodes peuvent être plus rapides que get dans certains cas aussi.L'une des raisons pour lesquelles le regroupement peut être rapide est que data.table inspecte j pour voir quelles colonnes il utilise, puis sous-ensembles uniquement les colonnes utilisées (FAQ 1.12 et 3.1).Il utilise base::all.vars(j) pour faire ça.Lors de l'utilisation get() dans j la colonne utilisée est masquée all.vars et data.table revient à sous-définir toutes les colonnes juste au cas où le j l'expression en a besoin (un peu comme lorsque le .SD le symbole est utilisé dans j, Pour qui .SDcols a été ajouté pour résoudre).Si toutes les colonnes sont utilisées de toute façon, cela ne fait aucune différence, mais si DT c'est-à-dire 1e7x100 puis un groupe j=sum(V1) devrait être beaucoup plus rapide qu'un groupe j=sum(get("V1")) pour cette raison.Au moins, c'est ce qui est censé se produire, et si ce n'est pas le cas, il s'agit peut-être d'un bug.Si par contre de nombreuses requêtes sont construites dynamiquement et répétées, alors le temps nécessaire pour paste0 et parse pourrait y entrer.Tout dépend vraiment.Paramètre verbose=TRUE devrait imprimer un message indiquant quelles colonnes ont été détectées comme étant utilisées par j, pour que cela puisse être vérifié.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top