web-dev-qa-db-fra.com

Référence aux colonnes data.table par des noms enregistrés dans des variables

data.table Est un package R fantastique et je l'utilise dans une bibliothèque que je développe. Jusqu'à présent, tout se passe très bien, sauf une complication. Il semble beaucoup plus difficile (par rapport aux trames de données conventionnelles) de faire référence aux colonnes data.table En utilisant des noms enregistrés dans des variables (comme pour les trames de données, par exemple: colname="col"; df[df[,colname]<5,colname]=0).

Peut-être ce qui complique le plus les choses est le manque apparent de cohérence de la syntaxe à ce sujet dans data.table. Dans certains cas, eval(colname) et get(colname), ou même c(colname) semblent fonctionner. Dans d'autres, DT[,colname, with=F] Est la solution. Pourtant, dans d'autres, comme par exemple les fonctions set() et subset(), je n'ai pas trouvé de solution du tout. Enfin, un cas d'utilisation extrême, bien que très courant, a été discuté plus tôt ( passage des noms de colonne à data.table par programme ) et les solutions proposées, bien qu'apparemment faisant leur travail, ne semblaient pas particulièrement lisibles ...

Peut-être que je complique trop les choses? Si quelqu'un pouvait noter une feuille de triche rapide pour faire référence aux noms de colonne data.table En utilisant des variables pour différents scénarios courants, je serais très reconnaissant.

MISE À JOUR:

Quelques exemples spécifiques qui fonctionnent à condition de pouvoir coder en dur les noms de colonnes:

x.short = subset(x, abs(dist)<=100)
set(x, which(x$val<10), "val", 0) 

Supposons maintenant distcol="dist", valcol="val". Quelle est la meilleure façon de faire ce qui précède en utilisant distcol et valcol, mais pas dist et val?

41
msp

Si vous allez effectuer des opérations compliquées dans vos expressions j, vous devriez probablement utiliser eval et quote. Un problème avec cela dans la version actuelle de data.table Est que l'environnement de eval n'est pas toujours correctement traité - eval et quote dans data.table (Remarque: il y a été une mise à jour de cette réponse basée sur une mise à jour du package.) - et le correctif actuel consiste à ajouter .SD à eval. Pour autant que je sache à partir de quelques tests que j'ai exécutés, cela n'affecte pas la vitesse (comme, par exemple, avoir .SD[1] Dans j).

Fait intéressant, ce problème ne fait qu'affecter le j et vous pourrez utiliser eval normalement dans i (où .SD N'est pas disponible de toute façon).

L'autre problème est l'affectation, et là, vous devez avoir des chaînes. Je connais une façon d'extraire le nom de la chaîne d'une expression citée - ce n'est pas joli, mais cela fonctionne. Voici un exemple combinant tout ensemble:

x = data.table(dist = c(1:10), val = c(1:10))
distcol = quote(dist)
valcol = quote(val)

x[eval(valcol) < 5,
  capture.output(str(distcol, give.head = F)) := eval(distcol)*sum(eval(distcol, .SD))]

Notez comment j'allais pas ajouter .SD Dans une eval(distcol), mais ce ne sera pas le cas si je la retire de l'autre eval.

Une autre option consiste à utiliser get:

diststr = "dist"
valstr = "val"

x[get(valstr) < 5, c(diststr) := get(diststr)*sum(get(diststr))]
22
eddi

Peut-être connaissez-vous déjà cette solution?

DT[[colname]]

Ceci est inspiré par la solution de @ eddi dans les commentaires ci-dessous, en utilisant l'exemple de l'OP:

set.seed(1)
x = data.table(a = 1:10, b=rnorm(10))
colstr="b"
col <- eval(parse(text=paste("quote(",colstr,")",sep="")))
x[eval(col)<0]
x[eval(col)<0,c(colstr):=-100]
7
Frank

Supposons que vous ayez le nom de la colonne dans la variable x, vous pouvez le faire

colname = as.name(x)

vous pouvez ensuite utiliser colname dans la fonction subset

4
saiteja

eval n'est certainement pas une approche recommandée pour sous-ensemble un data.table en utilisant des variables enregistrées dynamiquement. L'exemple suivant vous aidera:

# Toy data.table example
DT = data.table(a = c(1,2,3), b = c(4,5,6))

# Saved variable
mVar <- "a"

# Subset
DT[DT[[mVar]] < 2]

eval est très sensible aux expressions de caractères complexes et n'est généralement pas recommandé pour le code de production.

1
mammask