2017-06-20 52 views
0

這個問題給出瞭如何在by.x =by.y =參數轉換的基礎Rmergedata.table語法,連接鍵指定不同的名稱列的例子:如何使用指定和提取X和Y中的非平衡連接X [Y,...]中的變量?

data.table merge by multiple columns

但是,我不能工作不知道如何爲非等效連接做同樣的事情,而且我對輸出非常困惑。

示例數據:

set.seed(0) 
tmp_dt1<- data.table(grp = c(1,2), time = runif(100)) 
tmp_dt2 <- data.table(grp = c(1,2), time = c(0.1, 0.5)) 
tmp_dt2 <- tmp_dt2[, time_to := time + 0.2] 
tmp_dt2 <- tmp_dt2[, time_from := time] # for clarity, rename time variable 

我想通過grp以相等聯接兩個表,然後由非球菌加盟,使我只保留timetmp_dt1它屬於time_totime_from之間。從我可以告訴tmp_dt1[tmp_dt2, , on = c("grp", "time>=time", "time<=time_to")]做什麼,我想:

> tmp_dt1[tmp_dt2, , on = c("grp", "time>=time", "time<=time_to")] 
    grp time time.1 time_from 
1: 1 0.1 0.3  0.1 
2: 1 0.1 0.3  0.1 
3: 1 0.1 0.3  0.1 
4: 1 0.1 0.3  0.1 
5: 1 0.1 0.3  0.1 
6: 1 0.1 0.3  0.1 
7: 1 0.1 0.3  0.1 
... 

什麼讓我困惑的是,x.time缺失,產生的列名都非常混亂。例如,爲什麼有一列叫做time.1?我想澄清的語法讓tmp_dt1[tmp_dt2, , on = c("grp", "time>=y.time", "time<=y.time_to")]生產:

grp y.time y.time_to time_from 
1: 1 0.1 0.3  0.1 
2: 1 0.1 0.3  0.1 
3: 1 0.1 0.3  0.1 
4: 1 0.1 0.3  0.1 
5: 1 0.1 0.3  0.1 
6: 1 0.1 0.3  0.1 
7: 1 0.1 0.3  0.1 
... 

有的怎麼也解列x.time,除了所有列在y。不幸的是這個失敗,出現錯誤:

> tmp_dt1[tmp_dt2, , on = c("grp", "time>=y.time", "time<=y.time_to")] 
Error in `[.data.table`(tmp_dt1, tmp_dt2, , on = c("grp", "time>=y.time", : 
    Column(s) [y.time,y.time_to] not found in i 

嘗試以下也不會產生我所期望的,而不是我得到:

> tmp_dt1[tmp_dt2, .(grp, time, time_from = i.time, time_to = i.time_to), on = c("grp", "time>=time", "time<=time_to")] 
    grp time time_from time_to 
1: 1 0.1  0.1  0.3 
2: 1 0.1  0.1  0.3 
3: 1 0.1  0.1  0.3 
4: 1 0.1  0.1  0.3 
5: 1 0.1  0.1  0.3 
6: 1 0.1  0.1  0.3 
7: 1 0.1  0.1  0.3 

其中time列不承擔任何相似之處tmp_dt1$time

+0

確定,據我所知,如果使用'提供了'on'條件的連接密鑰匹配以下規則適用。()'或'C()'在'X [Y]'中。如果每個元素包含一個變量,則在兩個表中查找該變量。如果變量在方程的任一側提供,則在'X'表中查找LHS變量,在'Y'表中查找RHS變量。變量提取和最終列名對我來說仍然是一個謎。 – Alex

+1

最後的列名始終來自Y.每個條目在'on ='中有一個連接列。 – Frank

+0

您可能想澄清預期的結果。這是一個相當合理的事情:'tmp_dt1 [tmp_dt1 [tmp_dt2,on =。(grp,time> = time_from,time <= time_to),which = TRUE]]'將第一個表格子集化。我懷疑作爲重複的價值觀掛在下限和上限上是否有很多意義。 – Frank

回答

1

爲了避免混淆,我建議重命名兩個data.tables中具有相同名稱的列,並創建非等連接列的副本。

setnames(tmp_dt2, "time", "time_dt2") tmp_dt2[, c("time_from_join", "time_to_join"):=list(time_from, time_to)] tmp_dt1[ , time_join := time]

然後,我們可以加入,然後扔掉所有data.table混亂與非球菌加入臨時列。

tmp_dt1[tmp_dt2, on=.(grp==grp, time_join >= time_from_join, time_join <= time_to_join)][ , c("grp", "time", "time_from", "time_to", "time_dt2")]

grp time time_from time_to time_dt2 1: 1 0.1079436 0.1 0.3 0.1 2: 1 0.1216919 0.1 0.3 0.1 3: 1 0.1255551 0.1 0.3 0.1 4: 1 0.1433044 0.1 0.3 0.1 ...

1

我想你想是這樣的,使用dplyr:由grp1

library(dplyr) 
merged <- inner_join(tmp_dt1, tmp_dt2, by="grp") %>% 
      rowwise() %>% 
      filter(between(time.x, time_from, time_to)) %>% 
      ungroup() 

inner_join相等聯接。 rowwise()指定我希望以下語句按行發生。 filter()將按條件過濾行。條件使用between,詢問是time.x >= time_fromtime.x <= time_to。最後,ungroup按行,萬一你想要正常data.frame

+0

謝謝你,不幸的是我很確定這個非Equi加入使用dplyr需要更多內存比data.table版本。 – Alex

+0

爲什麼不使用data.table連接,然後管道到dplyr過濾器? – CPak

+0

data.table連接(非等分部分)已經完成了過濾。無論如何,我的問題是控制連接的輸入和輸出。 – Alex