web-dev-qa-db-fra.com

Comment fusionner deux data.table par des noms de colonne différents?

J'ai deux data.tableXetY.

colonnes dansX: area, id, value
colonnes dansY: ID, price, sales 

Créez les deux data.tables:

X = data.table(area=c('US', 'UK', 'EU'),
               id=c('c001', 'c002', 'c003'),
               value=c(100, 200, 300)
              )

Y = data.table(ID=c('c001', 'c002', 'c003'),
               price=c(500, 200, 400),
               sales=c(20, 30, 15)
              )

Et je mets les clés pourXetY:

setkey(X, id)
setkey(Y, ID)

Maintenant, j'essaie de rejoindreXetYpar id dansXet ID dansY:

merge(X, Y)
merge(X, Y, by=c('id', 'ID'))
merge(X, Y, by.x='id', by.y='ID')

Tous ont déclenché une erreur en indiquant que les noms de colonne dans l'argument by n'étaient pas valides.

J'ai fait référence au manuel de data.table et j'ai trouvé la fonction merge ne prenant pas en charge les arguments by.x et by.y.

Comment pourrais-je joindre deux data.tables par des noms de colonne différents sans changer les noms de colonne ?

Ajouter :
J'ai réussi à joindre les deux tables par X[Y], mais pourquoi la fonction merge échoue-t-elle dans data.table? 

23
Zelong

Utilisez cette opération:

X[Y]
#    area   id value price sales
# 1:   US c001   100   500    20
# 2:   UK c002   200   200    30
# 3:   EU c003   300   400    15

ou cette opération:

Y[X]
#      ID price sales area value
# 1: c001   500    20   US   100
# 2: c002   200    30   UK   200
# 3: c003   400    15   EU   300

Modifier après avoir modifié votre question, j'ai lu la section 1.12 du FAQ : "Quelle est la différence entre X [Y] et la fusion (X, Y)?", Ce qui m'a amené à la caisse ?merge et moi avons découvert qu'il existe deux fonctions de fusion différentes selon le package que vous utilisez. La valeur par défaut est merge.data.frame mais data.table utilise merge.data.table. Comparer

merge(X, Y, by.x = "id", by.y = "ID") # which is merge.data.table
# Error in merge.data.table(X, Y, by.x = "id", by.y = "ID") : 
# A non-empty vector of column names for `by` is required.

avec 

merge.data.frame(X, Y, by.x = "id", by.y = "ID")
#     id area value price sales
# 1 c001   US   100   500    20
# 2 c002   UK   200   200    30
# 3 c003   EU   300   400    15

Editer pour compléter sur la base d'un commentaire de @Michael Bernsteiner, il semble que l'équipe data.table envisage d'implémenter by.x et by.y dans la fonction merge.data.table, mais ne l'a pas encore fait.

14
Richard Erickson

À partir de data.table version 1.9.6 (sur CRAN le sep 2015), vous pouvez spécifier les arguments by.x et by.y dans data.table::merge

merge(x=X, y=Y, by.x="id", by.y="ID")[]
#     id area value price sales
#1: c001   US   100   500    20
#2: c002   UK   200   200    30
#3: c003   EU   300   400    15

Cependant, dans data.table 1.9.6, vous pouvez aussi spécifier l’argument on dans la notation X[Y].

La syntaxe X [Y] peut maintenant être jointe sans avoir à définir de clés à l'aide du nouvel argument on. Par exemple: DT1 [DT2, on = c (x = "y")] joindrait la colonne "y" de DT2 à "x" de DT1. DT1 [DT2, on = "y"] rejoindrait la colonne "y" des deux data.tables.

X[Y, on=c(id = "ID")]
#   area   id value price sales
#1:   US c001   100   500    20
#2:   UK c002   200   200    30
#3:   EU c003   300   400    15

this answer de l'auteur data.table a plus de détails

23
tospig

La fusion échoue lorsque vous utilisez by.x et by.y avec data.table. Prendre vos données:

> merge(X,Y, by.x='id', by.y='ID')
Error in merge.data.table(X, Y, by.x = "id", by.y = "ID")

Vous pouvez utiliser data.table avec fusion, mais vous devez utiliser l'argument by pour vous joindre (renommez donc les colonnes pour qu'elles aient le même colnames

Y = setNames(Y,c('id','price','sales'))

Cela ne fonctionnera toujours pas:

merge(X,Y, by.x='id', by.y='id')
Error in merge.data.table(X, Y, by.x = "id", by.y = "id") :

Mais cela fonctionnera:

> merge(X,Y, by='id')
#     id area value price sales
#1: c001   US   100   500    20
#2: c002   UK   200   200    30
#3: c003   EU   300   400    15

Sinon, vous devez convertir data.table en data.frame pour pouvoir utiliser merge avec les arguments by.x et by.y:

merge(data.frame(X), data.frame(Y), by.x='id', by.y='ID')
3
Colonel Beauvel

Vous pouvez également fusionner en utilisant plusieurs colonnes portant des noms différents. voir exemple ci-dessous

# create data frame authors
authors <- data.frame(
FirstName=c("Lorne", "Loren", "Robin",
              "Robin", "Billy"),
LastName=c("Green", "Jaye", "Green",
             "Howe", "Jaye"),
Age=c(82, 40, 45, 2, 40),
Income=c(1200000, 40000, 25000, 0, 27500),
Home=c("California", "Washington", "Washington",
    "Alberta", "Washington"))

# create data frame books Note First name in authors is same as AuthorFirstname same thing with lastname.
books <- data.frame(
        AuthorFirstName=c("Lorne", "Loren", "Loren",
            "Loren", "Robin", "Rich"),
        AuthorLastName=c("Green", "Jaye", "Jaye", "Jaye",
            "Green", "Calaway"),
        Book=c("Bonanza", "Midwifery", "Gardening",
        "Perennials", "Who_dun_it?", "Support"))

merge(authors, books, by.x=c("FirstName", "LastName"),
      by.y=c("AuthorFirstName", "AuthorLastName"),
      all.x=TRUE)
1
Akshay Kadidal