繁体   English   中英

条件合并或左连接 R 中的两个数据帧

[英]conditional merge or left join two dataframes in R

我正在尝试将参考表中的其他数据添加到我的主 dataframe 中。 我看到有人问过类似的问题,但是找不到适合我的具体案例的任何东西。

我的数据框的一个例子是这样设置的

df <- data.frame("participant" = rep(1:3,9), "time" = rep(1:9, each = 3))
lookup <- data.frame("start.time" = c(1,5,8), "end.time" = c(3,6,10), "var1" = c("A","B","A"),
                     "var2" = c(8,12,3), "var3"= c("fast","fast","slow"))

print(df)
       participant time
    1            1    1
    2            2    1
    3            3    1
    4            1    2
    5            2    2
    6            3    2
    7            1    3
    8            2    3
    9            3    3
    10           1    4
    11           2    4
    12           3    4
    13           1    5
    14           2    5
    15           3    5
    16           1    6
    17           2    6
    18           3    6
    19           1    7
    20           2    7
    21           3    7
    22           1    8
    23           2    8
    24           3    8
    25           1    9
    26           2    9
    27           3    9

> print(lookup)
  start.time end.time var1 var2 var3
1          1        3    A    8 fast
2          5        6    B   12 fast
3          8       10    A    3 slow

我想要做的是以某种方式合并或连接这两个数据帧,其中还包括查找数据帧的开始时间和结束时间之间的时间。 因此,在时间位于开始时间和结束时间之间的每个实例中,列 var1、var2 和 var3 都会添加到 df 中。

例如,在上述情况下 - 第一行中的查找值的开始时间为 1,结束时间为 3,因此对于每个参与者的时间 1、2 和 3,应添加第一行数据。

output 应该看起来像这样。

print(output)
   participant time var1 var2 var3
1            1    1    A    8 fast
2            2    1    A    8 fast
3            3    1    A    8 fast
4            1    2    A    8 fast
5            2    2    A    8 fast
6            3    2    A    8 fast
7            1    3    A    8 fast
8            2    3    A    8 fast
9            3    3    A    8 fast
10           1    4 <NA>   NA <NA>
11           2    4 <NA>   NA <NA>
12           3    4 <NA>   NA <NA>
13           1    5    B   12 fast
14           2    5    B   12 fast
15           3    5    B   12 fast
16           1    6    B   12 fast
17           2    6    B   12 fast
18           3    6    B   12 fast
19           1    7 <NA>   NA <NA>
20           2    7 <NA>   NA <NA>
21           3    7 <NA>   NA <NA>
22           1    8    A    3 slow
23           2    8    A    3 slow
24           3    8    A    3 slow
25           1    9    A    3 slow
26           2    9    A    3 slow
27           3    9    A    3 slow

我意识到列名不匹配,它们应该用于合并数据集。

一种选择是使用sqldf package,并将您的问题表述为 SQL 左连接:

sql <- "SELECT t1.participant, t1.time, t2.var1, t2.var2, t2.var3
        FROM df t1
        LEFT JOIN lookup t2
            ON t1.time BETWEEN t2.\"start.time\" AND t2.\"end.time\""
output <- sqldf(sql)

dplyr解决方案:

output <- df %>% 
# Create an id for the join 
mutate(merge_id=1) %>% 
# Use full join to create all the combinations between the two datasets
full_join(lookup  %>% mutate(merge_id=1), by="merge_id") %>% 
# Keep only the rows that we want
filter(time >= start.time, time <= end.time) %>% 
# Select the relevant variables
select(participant,time,var1:var3) %>% 
# Right join with initial dataset to get the missing rows
right_join(df, by = c("participant","time")) %>% 
# Sort to match the formatting asked by OP
arrange(time, participant)

这会产生 OP 要求的 output,但它仅适用于合理大小的数据,因为完全连接会产生一个数据帧,其行数等于两个初始数据集的行数的乘积。

使用tidyverse并创建一个辅助表:

df <- data.frame("participant" = rep(1:3,9), "time" = rep(1:9, each = 3))
lookup <- data.frame("start.time" = c(1,5,8), "end.time" = c(3,6,10), "var1" = c("A","B","A"),
                     "var2" = c(8,12,3), "var3"= c("fast","fast","slow"))

lookup_extended <- lookup %>% 
    mutate(time = map2(start.time, end.time, ~ c(.x:.y))) %>% 
    unnest(time) %>% 
    select(-start.time, -end.time)

df2 <- df %>% 
    left_join(lookup_extended, by = "time")

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM