2010-02-09 11 views
43

note: cette question et les réponses suivantes se rapportent à data.table versions < 1.5.3; v. 1.5.3 a été publié en février 2011 pour résoudre ce problème. voir un traitement plus récent (03-2012): Translating SQL joins on foreign keys to R data.table syntaxComment faire une opération de fusion de données.table


J'ai fouillais dans la documentation du data.table package (remplacement de data.frame qui est beaucoup plus efficace pour certaines opérations), y compris Josh Reich's presentation on SQL and data.table at the NYC R Meetup (pdf), mais ne peut pas comprendre cette opération totalement triviale.

> x <- DT(a=1:3, b=2:4, key='a') 
> x 
    a b 
[1,] 1 2 
[2,] 2 3 
[3,] 3 4 
> y <- DT(a=1:3, c=c('a','b','c'), key='a') 
> y 
    a c 
[1,] 1 a 
[2,] 2 b 
[3,] 3 c 
> x[y] 
    a b 
[1,] 1 2 
[2,] 2 3 
[3,] 3 4 
> merge(x,y) 
    a b c 
1 1 2 a 
2 2 3 b 
3 3 4 c 

Les docs disent « Quand [le premier argument] est lui-même un data.table, une jointure est appelée similaire à la base :: fusion, mais utilise la recherche binaire sur la clé de tri. » Clairement ce n'est pas le cas. Puis-je obtenir les autres colonnes de y dans le résultat de x [y] avec data.tables? Il semble que ce soit juste en prenant les lignes de x où la touche correspond à la clé de y, mais en ignorant le reste de y entièrement ...

+2

Ceci a été résolu par v1.5.3 publié à CRAN en février 2011. S'il vous plaît voir c'est NEWS, nouvelle? Data.table et FAQ corrigé. –

Répondre

27

Vous citez la mauvaise partie de la documentation. Si vous avez un oeil à la doc de [.data.table vous lire:

Quand i est un data.table, x doit avoir une clé , ce qui signifie joindre i à x et retour les lignes qui correspondent à x. Une équi-jointure est effectuée entre chaque colonne dans i pour chaque colonne dans la clé de x dans l'ordre. Ceci est similaire à la base R fonctionnalité de sous-ensembles de matrice par une matrice à 2 colonnes, et dans dimensions supérieures de sous-ensembles d'un tableau à n dimensions par une matrice n-colonne

I admettent la La description du paquet (la partie que vous avez citée) est quelque peu confuse, car il semble dire que l'opération "[" peut être utilisée à la place de la fusion. Mais je pense que ce qu'il dit est: si x et y sont tous les deux data.tables, nous utilisons une jointure sur un index (qui est invoqué comme fusion) au lieu de la recherche binaire.


Encore une chose:

La bibliothèque data.table J'ai installé via install.packages il manquait le merge.data.table method, donc l'utilisation merge appellerait merge.data.frame. Après avoir installé le package from R-Forge R utilisé la méthode merge.data.table plus rapide.

Vous pouvez vérifier si vous avez la méthode merge.data.table en vérifiant la sortie:

methods(generic.function="merge") 

EDIT [réponse plus valide]: Cette réponse fait référence à data.table version 1.3. Dans la version 1.5.3, le comportement de data.table a changé et x [y] renvoie les résultats attendus. Merci Matthew Dowle, auteur de data.table, de le signaler dans les commentaires.

+0

Ah. Il semble que la version sur CRAN soit la version 1.2, alors que la version sur R-Forge est la version 1.3. La méthode 'merge' a été ajoutée en 1.3. D'après ce que je peux dire en regardant autour de R-Forge, la méthode a été ajoutée quelque chose comme il y a 8 mois, donc je ne sais pas pourquoi ce n'est pas encore sur CRAN! – Harlan

+5

La syntaxe X [Y] a été changée dans la version 1.5.3 publiée sur CRAN en février 2011. Veuillez voir les NOUVELLES, la nouvelle? Data.table et la FAQ corrigée. –

3

Je pense que f3lix est correct et que la documentation est un peu trompeuse. L'avantage est de faire une jointure rapide pour sous-ensemble les données.Vous devez toujours utiliser la fonction merge ultérieurement comme dans l'exemple ci-dessus.

Vous verrez dans Josh's presentation on using data.table que voici comment son exemple fonctionne. Il a d'abord sous-ensembles l'un des data.tables, fait alors une fusion:

library(data.table) 
sdt <- DT(series, key='series_id') 
ddt <- DT(data, key='series_id') 
u <- sdt[ grepl('^[A-Z]{2}URN', fred_id) & !grepl('DSURN', fred_id) ] 
d <- ddt[ u, DT(min=min(value)), by='series_id', mult='all'] 
data <- merge(d,series)[,c('title','min','mean','max')] 
+0

Merci, Shane. J'ai été très confus par cela, car je savais (ou je pensais que je savais) que 'merge' ne tirerait pas parti des avantages de' data.table'. – Harlan

14

Merci pour les réponses. J'ai raté ce fil quand il a été posté à l'origine. data.table a déménagé depuis février. 1.4.1 a été publié à CRAN il y a un certain temps et 1.5 sera bientôt disponible. Par exemple, l'alias DT() a été remplacé par list(); comme primitive la plus rapide, et data.table hérite maintenant de data.frame il fonctionne avec des paquets qui ne acceptent data.frame tels que ggplot et treillis, sans conversion nécessaire (plus rapide et plus pratique).

Est-il possible de souscrire à l'étiquette data.table si je reçois un e-mail quand quelqu'un poste une question avec cette étiquette? La liste datable-help a augmenté à environ 30-40 messages par mois, mais je suis heureux de répondre ici si je peux obtenir une sorte de notification.

Matthew

+1

Salut, merci pour la note! Oui, c'est définitivement possible. Cliquez sur la balise 'data.table' dans le coin supérieur droit de l'écran, puis faites défiler vers le bas jusqu'à ce que vous voyiez l'icône RSS, et utilisez-la pour vous abonner aux questions avec cette balise. – Harlan

+0

Merci Harlan. J'ai souscrit maintenant. –

9

Je pense en utilisant la fonction base::merge n'est pas nécessaire, car l'utilisation data.table peut être joint beaucoup plus rapide. Par exemple. voir ce qui suit. Je fais x et y data.tables avec 3-3 colonnes:

> x <- data.table(foo = 1:5, a=20:24, zoo = 5:1) 
> y <- data.table(foo = 1:5, b=30:34, boo = 10:14) 
> setkey(x, foo) 
> setkey(y, foo) 

et fusionner les deux avec base:merge et data.table pour voir la se joint à la vitesse des exécutions:

> system.time(merge(x,y)) 
    user system elapsed 
    0.027 0.000 0.023 
> system.time(x[,list(y,x)]) 
    user system elapsed 
    0.003 0.000 0.006 

Les résultats ne sont pas identiques, comme celui-ci a une colonne supplémentaire:

> merge(x,y) 
    foo a zoo b boo 
[1,] 1 20 5 30 10 
[2,] 2 21 4 31 11 
[3,] 3 22 3 32 12 
[4,] 4 23 2 33 13 
[5,] 5 24 1 34 14 
> x[,list(x,y)] 
    foo a zoo foo.1 b boo 
[1,] 1 20 5  1 30 10 
[2,] 2 21 4  2 31 11 
[3,] 3 22 3  3 32 12 
[4,] 4 23 2  4 33 13 
[5,] 5 24 1  5 34 14 

Ce qui ne pouvait pas faire un gros problème :)

+3

Merci, c'est intéressant. Une syntaxe entièrement non évidente, cependant! Si je devais utiliser cela, je pourrais redéfinir une fonction qui fait fonction (x, y) x [, list (x, y)] 'ou quelque chose, peut-être laisser tomber cette colonne de clé supplémentaire trop ... – Harlan

+2

Je pense que le bon La syntaxe des jointures dans data.table est en fait x [y] ou x [y,], c'est-à-dire que les jointures doivent utiliser le premier index. Cela donne les mêmes résultats que la fusion. notez que x [y] et y [x] n'ont pas besoin d'être identiques, c'est-à-dire si y contient des entrées dans foo qui ne sont pas représentatives de x. Peut-être que j'ai raté quelque chose, mais voir Joins dans le data.table [vignette] (http://cran.r-project.org/web/packages/data.table/vignettes/datatable-intro.pdf) – cboettig

+1

ci-dessus x [, list (x, y)] n'a pas fonctionné pour moi. J'ai essayé x [, c (x, y)] et cela a fonctionné. Je ne suis pas sûr que cela ait un sens. – bala