2015-11-07 5 views
4

Je suis en train de faire un min/max global sur une choisie dynamiquement colonne dans un data.table. Cela fonctionne parfaitement pour les colonnes numeric mais je ne peux pas l'obtenir pour travailler sur les colonnes Date sauf si je crée un data.table temporaire.R: data.table agrégations .dynamic sur colonne colonnes Date

Il fonctionne quand j'utilise le nom:

dt <- data.table(Index=1:31, Date = seq(as.Date('2015-01-01'), as.Date('2015-01-31'), by='days')) 
dt[, .(minValue = min(Date), maxValue = max(Date))] 
# minValue maxValue 
# 1: 2015-01-01 2015-01-31 

Il ne fonctionne pas lorsque j'utilise with=FALSE:

colName = 'Date' 
dt[, .(minValue = min(colName), maxValue = max(colName)), with=F] 
# Error in `[.data.table`(dt, , .(minValue = min(colName), maxValue = max(colName)), : 
# could not find function "." 

je peux utiliser .SDcols sur une colonne numérique:

colName = 'Index' 
dt[, .(minValue = min(.SD), maxValue = max(.SD)), .SDcols=colName] 
# minValue maxValue 
# 1:  1  31 

Mais j'obtiens une erreur quand je fais la même chose pour une colonne Date:

colName = 'Date' 
dt[, .(minValue = min(.SD), maxValue = max(.SD)), .SDcols=colName] 
# Error in FUN(X[[i]], ...) : 
# only defined on a data frame with all numeric variables 

Si je lapply(.SD, min) ou sapply() alors les dates sont modifiées en chiffres.

Ce qui suit fonctionne et ne semble pas perdre de mémoire et est rapide. Y a-t-il quelque chose de mieux?

a <- dt[, colName, with=F] 
setnames(a, 'a') 
a[, .(minValue = min(a), maxValue = max(a))] 
+0

Réponse courte: Utilisez '.SD [[1]]' 'parce que .SD' est une liste de vecteurs et que vous souhaitez utiliser la premier vecteur dedans. Réponse longue: vous semblez avoir trouvé une faille bizarre où un data.frame de tous les cols numériques peut avoir ses 'max' et' min' pris; et je ne voudrais pas construire sur cette exception étrange. – Frank

Répondre

2

Sur votre première tentative:

dt[, .(minValue = min(colName), maxValue = max(colName)), with=F] 
# Error in `[.data.table`(dt, , .(minValue = min(colName), maxValue = max(colName)), : 
# could not find function "." 

Vous devriez lire simplement la vignette Introduction to data.table pour comprendre ce que with= moyens. Il est plus facile si vous êtes au courant de la fonction with() de la base R.

Sur le second:

dt[, .(minValue = min(.SD), maxValue = max(.SD)), .SDcols=colName] 
# Error in FUN(X[[i]], ...) : 
# only defined on a data frame with all numeric variables 

Cela semble être un problème avec min() et max() sur un data.frame/data.table avec colonne avec des attributs. Voici un MRE.

df = data.frame(x=as.Date("2015-01-01")) 
min(df) 
# Error in FUN(X[[i]], ...) : 
# only defined on a data frame with all numeric variables 

Pour répondre à votre question, vous pouvez utiliser get():

dt[, .(min = min(get(colName)), max = max(get(colName)))] 

Ou comme @Frank a suggéré, [[ opérateur de sous-ensemble de la colonne:

dt[, .(min = min(.SD[[colName]]), max = max(.SD[[colName]]))] 

Il n'y a pas encore d'une manière plus agréable d'appliquer .SD à plusieurs fonctions (car la base R ne semble pas avoir un AFAICT, et data.table essaie d'utiliser autant que possible les fonctions de base R). Il y a un FR #1063 pour résoudre ce problème. Si/quand cela soit mis en oeuvre, alors on pourrait faire, par exemple:

# NOTE: not yet implemented, FR #1063 
dt[, colwise(.SD, min, max), .SDcols = colName] 
+0

En pensant à cela colwise, ... une solution de contournement maladroite pour le cas OP est 'dcast (dt,. ~., Valeur.var =" Date ", fun = liste (min, max))' ou 'dcast (dt, . ~., valeur.var = noms (dt), fun = liste (min, max)) 'faire les deux vars à la fois. – Frank