通过data.table roll ='nearest'函数合并两组数据

时间:2019-01-02 21:35:53

标签: r merge data.table

我有两组数据。

set_A的样本(总行数:45467):

ID_a    a1  a2  a3  time_a
2   35694   5245.2  301.6053    00.00944
3   85694   9278.9  301.6051    23.00972
4   65694   9375.2  301.6049    22.00972
5   85653   4375.5  301.6047    19.00972
6   12694   5236.3  301.6045    22.00972
7   85697   5345.2  301.6043    21.00972
8   85640   5274.1  301.6041    20.01000
9   30694   5279.0  301.6039    20.01000

set_B的样本(总行数:4798):

ID_b    b1  b2  source  time_b
2   34.20   15.114  set1.csv.1  20.35750
7   67.20   16.114  set1.csv.2  21.35778
12  12.20   33.114  set1.csv.3  22.35806
17  73.20   67.114  set2.csv.1  23.35833
23  88.20   42.114  set2.csv.2  19.35861
28  90.20   52.114  set3.csv.1  00.35889

我对以下结果感兴趣:set_B中来自set_A的行被time_atime_b的最接近值匹配(输出行的总数: 4798)。在set_A中,time_a的值可以重复多次(例如ID_a[8,][ID_a[9,])-哪一行将与{ {1}}(在这种情况下为set_B)。预期结果的示例:

ID_b[1,]

我在stackoverflow上遇到了许多类似的问题,我非常喜欢ID_b b1 b2 source time_b ID_a a1 a2 a3 time_a 2 34.20 15.114 set1.csv.1 20.35750 8 85640 5274.1 301.6041 20.01000 7 67.20 16.114 set1.csv.2 21.35778 7 85697 5345.2 301.6043 21.00972 12 12.20 33.114 set1.csv.3 22.35806 4 65694 9375.2 301.6049 22.00972 17 73.20 67.114 set2.csv.1 23.35833 3 85694 9278.9 301.6051 23.00972 23 88.20 42.114 set2.csv.2 19.35861 5 85653 4375.5 301.6047 19.00972 28 90.20 52.114 set3.csv.1 00.35889 2 35694 5245.2 301.6053 00.00944 库代码,因为它们看起来非常优雅。但是,我进行了几次失败的尝试,都收到了一个基于两组集合的表(总行数45467),或者仅将一个列data.table合并到time_a ...但是,我还是赢了别太挑剔,如果有人有其他想法,我将非常感谢您的帮助。

我正在处理的代码示例:

set_B

结果,我不仅收到一个表,其中的数据应该被否定,而且还收到列名中的“乱七八糟”(例如,包含setDT(set_B) setDT(set_A) setkey(set_B, time_b) [, time_a:=time_b] test_ab <- set_B[set_A, roll='nearest'] 值的列称为ID_a)。 / p>

我真的很感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

这是基于您提供的示例数据的分步示例:

# Sample data
library(data.table)
setDT(set_A)
setDT(set_B)    

# Create time column by which to do a rolling join
set_A[, time := time_a]
set_B[, time := time_b]
setkey(set_A, time)
setkey(set_B, time)

# Rolling join by nearest time
set_merged <- set_B[set_A, roll = "nearest"]

unique(set_merged[order(ID_b)], by = "time")
#    ID_b   b1     b2     source   time_b     time ID_a    a1     a2       a3
# 1:    2 34.2 15.114 set1.csv.1 20.35750 20.01000    8 85640 5274.1 301.6041
# 2:    7 67.2 16.114 set1.csv.2 21.35778 21.00972    7 85697 5345.2 301.6043
# 3:   12 12.2 33.114 set1.csv.3 22.35806 22.00972    4 65694 9375.2 301.6049
# 4:   17 73.2 67.114 set2.csv.1 23.35833 23.00972    3 85694 9278.9 301.6051
# 5:   23 88.2 42.114 set2.csv.2 19.35861 19.00972    5 85653 4375.5 301.6047
# 6:   28 90.2 52.114 set3.csv.1  0.35889  0.00944    2 35694 5245.2 301.6053
#      time_a
# 1: 20.01000
# 2: 21.00972
# 3: 22.00972
# 4: 23.00972
# 5: 19.00972
# 6:  0.00944

两条评论:

  1. 我们创建了一个新的time列,以避免丢失set_Aset_B中的原始时间列之一。如果需要,您随时可以在连接后删除time列。
  2. 我们使用unique按照time的顺序删除重复的ID_b行。您在帖子中提到“合并哪一行并不重要” ,但是如果您确实想保留特定于 行,则可能需要进行调整这行代码。

更新(感谢@Henrik)

正如@Henrik所指出的,实际上,您所追求的只是set_Aset_B的滚动连接,在这种情况下,您不需要处理重复的行。 / p>

翻译为

library(data.table)
setDT(set_A)
setDT(set_B)    

# Create time column by which to do a rolling join
set_A[, time := time_a]
set_B[, time := time_b]

set_A[set_B, on = "time", roll = "nearest"][order(ID_a)]
#   ID_a    a1     a2       a3   time_a     time ID_b   b1     b2     source
#1:    2 35694 5245.2 301.6053  0.00944  0.35889   28 90.2 52.114 set3.csv.1
#2:    3 85694 9278.9 301.6051 23.00972 23.35833   17 73.2 67.114 set2.csv.1
#3:    5 85653 4375.5 301.6047 19.00972 19.35861   23 88.2 42.114 set2.csv.2
#4:    6 12694 5236.3 301.6045 22.00972 22.35806   12 12.2 33.114 set1.csv.3
#5:    7 85697 5345.2 301.6043 21.00972 21.35778    7 67.2 16.114 set1.csv.2
#6:    9 30694 5279.0 301.6039 20.01000 20.35750    2 34.2 15.114 set1.csv.1
#  time_b
#1:  0.35889
#2: 23.35833
#3: 19.35861
#4: 22.35806
#5: 21.35778
#6: 20.35750

样本数据

set_A <- read.table(text =
    "ID_a    a1  a2  a3  time_a
2   35694   5245.2  301.6053    00.00944
3   85694   9278.9  301.6051    23.00972
4   65694   9375.2  301.6049    22.00972
5   85653   4375.5  301.6047    19.00972
6   12694   5236.3  301.6045    22.00972
7   85697   5345.2  301.6043    21.00972
8   85640   5274.1  301.6041    20.01000
9   30694   5279.0  301.6039    20.01000", header = T)

set_B <- read.table(text =
    "ID_b    b1  b2  source  time_b
2   34.20   15.114  set1.csv.1  20.35750
7   67.20   16.114  set1.csv.2  21.35778
12  12.20   33.114  set1.csv.3  22.35806
17  73.20   67.114  set2.csv.1  23.35833
23  88.20   42.114  set2.csv.2  19.35861
28  90.20   52.114  set3.csv.1  00.35889", header = T)