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

bar*_*rka 5 merge r 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
Run Code Online (Sandbox Code Playgroud)

样本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
Run Code Online (Sandbox Code Playgroud)

我对结果感兴趣,其中set_B、 的行与和的set_A最接近的值匹配(输出行总数:4798)。In的值可以重复多次(例如和) - 哪一行将与来自的行合并(在本例中为)并不重要。预期结果示例:time_atime_bset_Atime_aID_a[8,][ID_a[9,]set_BID_b[1,]

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
Run Code Online (Sandbox Code Playgroud)

我在 stackoverflow 上遇到了很多类似的问题,我真的很喜欢data.table库代码,因为它们看起来非常优雅。然而,我做了几次失败的尝试,我收到了一个基于两组(总行数 45467)构建的表,或者仅将一列合并time_aset_B...不过,我不会挑剔,如果有人有其他想法我将非常感谢您的帮助。

我正在处理的代码示例:

setDT(set_B)
setDT(set_A)
setkey(set_B, time_b) [, time_a:=time_b]
test_ab <- set_B[set_A, roll='nearest']
Run Code Online (Sandbox Code Playgroud)

结果,我不仅收到一个包含应被忽略的数据的表,而且收到列名称中的“混乱”(例如,包含ID_a值的列称为time_a)。

我真的很感谢你的帮助!

Mau*_*ers 7

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

# 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
Run Code Online (Sandbox Code Playgroud)

两条评论:

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

更新(感谢@Henrik)

set_A正如@Henrik 指出的,您所追求的实际上是关于 的滚动联接set_B,在这种情况下您不需要处理重复的行。

这意味着

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
Run Code Online (Sandbox Code Playgroud)

样本数据

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)
Run Code Online (Sandbox Code Playgroud)

  • 就我个人而言,我喜欢使用 `on` 参数,而不是设置键。在 `x[i, on = , ...]` 中,明确了您要加入的内容。[此处](/sf/ask/90991001/#34219998)有一些很好的例子。干杯 (4认同)