web-dev-qa-db-ja.com

異なる列名で2つのdata.tableをマージする方法は?

2つのdata.table [〜#〜] x [〜#〜][〜#〜] y [〜#〜]があります。

[〜#〜] x [〜#〜]area, id, valueの列
[〜#〜] y [〜#〜]ID, price, sales

2つの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)
              )

そして、[〜#〜] x [〜#〜][〜#〜] y [〜#〜]にキーを設定します:

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

今私は[〜#〜] x [〜#〜][〜#〜] y [〜#〜]idで結合しようとしています[〜#〜] x [〜#〜]およびID in [〜#〜] y [〜#〜]

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

by引数の列名が無効であるというエラーが発生しました。

Data.tableのマニュアルを参照しましたが、merge関数がby.xおよびby.y引数をサポートしていないことがわかりました。

異なる列名で2つのdata.tablesを結合するにはどうすればいいですか?列名を変更せずに

追加
X[Y]で2つのテーブルを結合できましたが、data.tableでmerge関数が失敗するのはなぜですか?

27
Zelong

この操作を使用します。

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

またはこの操作:

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

Edit質問を編集した後、 [〜#〜] faq [〜#〜] のセクション1.12を読みました。 「X [Y]とmerge(X、Y)の違いは何ですか?」ということで、?mergeをチェックアウトし、使用しているパッケージに応じて2つの異なるマージ関数があることを発見しました。デフォルトはmerge.data.frameですが、data.tableはmerge.data.tableを使用します。比較する

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.

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

完全性の編集@ -Michael Bernsteinerによる コメント に基づいて、data.tableチームが計画しているように見えますby.xおよびby.ymerge.data.table関数に実装していますが、まだ実装していません。

16

data.tableバージョン1.9.6(2015年9月のCRAN)では、by.xby.yおよび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

ただし、data.table 1.9.6では、alsoX[Y]表記でon引数を指定できます

X [Y]構文は、新しいon引数を使用してキーを設定することなく結合できるようになりました。たとえば、DT1 [DT2、on = c(x = "y")]は、DT2の列 "y"をDT1の "x"に結合します。 DT1 [DT2、on = "y"]は、両方のdata.tablesの列 "y"を結合します。

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

この答えdata.table作成者による詳細

26
tospig

by.xおよびby.ydata.tableを使用すると、マージが失敗します。データの取得:

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

Mergeでdata.tableを使用できますが、結合にはby引数を使用する必要があります(したがって、同じcolnamesを持つように列の名前を変更します)

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

これはまだ機能しません:

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

しかし、これは動作します:

> 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

または、data.tableおよびdata.frame引数でmergeを使用するには、by.xby.yに変換する必要があります。

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

名前の異なる複数の列を使用してマージすることもできます。以下の例を参照してください

# 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