R-根据最近的日期合并数据框
R- merge dataframes based on recent dates
我有两个数据框:
在 DF1 中,对于每个 ID
,param
已被记录在不同的日期。
在 DF2 中,对于每个 ID
,给出了一些日期。
对于每个 ID
,我想从 DF1 获取所有相应的 param
和 value
,具体取决于日期:
value
对应最近的 date1
(in DF1
) before date2
(in DF2
)对于给定的参数或
如果没有这样的date1
,最近的value
afterdate2
.
DF1
是(我用 * 标记了结果的正确行):
ID date1 param value
1 id1 1/1/2020 pA pA_1_1
2 id1 2/1/2020 pA pA_1_2 *
3 id1 17/1/2020 pA pA_1_3
4 id1 20/1/2020 pB pB_1_1 *
5 id1 21/1/2020 pB pB_1_2
6 id2 21/12/2022 pA pA_2_1 *
7 id2 22/12/2022 pA pA_2_2
8 id2 18/12/2022 pB pB_2_1 *
9 id2 19/12/2022 pB pB_2_2
DF2
是:
ID date2
1 id1 15/1/2020
2 id2 20/12/2020
结果应该是:
ID date2 param value date1
1 id1 15/1/2020 pA pA_1_2 2/1/2020
2 id1 15/1/2020 pB pB_1_1 20/1/2020
3 id2 20/12/2020 pA pA_2_1 21/12/2022
4 id2 20/12/2020 pB pB_2_1 18/12/2022
重现 DF1
和 DF2
的代码:
DF1= data.frame(
stringsAsFactors = FALSE,
ID = c("id1","id1","id1","id1",
"id1","id2","id2","id2","id2"),
date1 = c("1/1/2020","2/1/2020",
"17/1/2020","20/1/2020","21/1/2020","21/12/2022",
"22/12/2022","18/12/2022","19/12/2022"),
param = c("pA", "pA", "pA", "pB", "pB", "pA", "pA", "pB", "pB"),
value = c("pA_1_1","pA_1_2","pA_1_3",
"pB_1_1","pB_1_2","pA_2_1","pA_2_2","pB_2_1","pB_2_2")
)
DF2=data.frame(
stringsAsFactors = FALSE,
ID = c("id1", "id2"),
date2 = c("15/1/2020", "20/12/2020")
)
这是我的解决方案。我确定有一种方法可以用更少的代码编写它(使用一个数据帧而不是两个数据帧,然后再合并)。但是我现在还不知道。
library(tidyverse)
library(lubridate)
# Get before date2
before <- DF1 %>%
left_join(DF2,by = "ID") %>%
mutate(diff = dmy(date1)-dmy(date2)) %>%
mutate(Grp = data.table::rleid(param)) %>%
filter(diff < 0) %>%
group_by(Grp) %>%
filter(diff == max(diff)) %>%
ungroup
# Get after date2
after <- DF1 %>%
left_join(DF2,by = "ID") %>%
mutate(diff = dmy(date1)-dmy(date2)) %>%
mutate(Grp = data.table::rleid(param)) %>%
filter(diff > 0) %>%
group_by(Grp) %>%
filter(! Grp %in% before$Grp, diff == min(diff)) %>%
ungroup
result <- bind_rows(before,after) %>%
select(ID,date2, param, value, date1) %>%
arrange(ID, param)
说明:我正在使用 lubridate 库来比较日期。我执行相同的过程来创建两个数据帧 - 第一个(在 df 之前)用于完成第一个条件的组(DF1 中最近的日期在 DF2 中的 date2 之前),第二个(在 df 之后)用于相反方向的组(最近的DF1 中的日期在 DF2 中的 date2 之后)。
我先解释一下:
# Get before date2
before <- DF1 %>%
left_join(DF2,by = "ID") %>%
mutate(diff = dmy(date1)-dmy(date2)) %>%
mutate(Grp = data.table::rleid(param)) %>%
filter(diff < 0) %>%
group_by(Grp) %>%
filter(diff == max(diff)) %>%
ungroup
在这里,我们通过ID合并DF1和DF2,因此具有相同ID的行具有相同的date2。然后,我们计算 date1-date2 的差异 - 首先我们使用 dmy()
将字符转换为日期。因此,date2 之前的日期将是负差异。使用 data.table::rleid(param)
我们枚举具有不同 ID 和参数的子组,因此我们可以知道子组。然后我们可以按 then 分组并按它们过滤。
最后:
result <- bind_rows(before,after) %>%
select(ID,date2, param, value, date1) %>%
arrange(ID, param)
我们按行绑定两个数据框,select 您要查找的列,以删除我们创建的用于操作的列(组和过滤器)。
PS:我添加了 arrange() 以确保最终的 df 按 ID 和参数值排序。
我有两个数据框:
在 DF1 中,对于每个 ID
,param
已被记录在不同的日期。
在 DF2 中,对于每个 ID
,给出了一些日期。
对于每个 ID
,我想从 DF1 获取所有相应的 param
和 value
,具体取决于日期:
value
对应最近的 date1
(in DF1
) before date2
(in DF2
)对于给定的参数或
如果没有这样的date1
,最近的value
afterdate2
.
DF1
是(我用 * 标记了结果的正确行):
ID date1 param value
1 id1 1/1/2020 pA pA_1_1
2 id1 2/1/2020 pA pA_1_2 *
3 id1 17/1/2020 pA pA_1_3
4 id1 20/1/2020 pB pB_1_1 *
5 id1 21/1/2020 pB pB_1_2
6 id2 21/12/2022 pA pA_2_1 *
7 id2 22/12/2022 pA pA_2_2
8 id2 18/12/2022 pB pB_2_1 *
9 id2 19/12/2022 pB pB_2_2
DF2
是:
ID date2
1 id1 15/1/2020
2 id2 20/12/2020
结果应该是:
ID date2 param value date1
1 id1 15/1/2020 pA pA_1_2 2/1/2020
2 id1 15/1/2020 pB pB_1_1 20/1/2020
3 id2 20/12/2020 pA pA_2_1 21/12/2022
4 id2 20/12/2020 pB pB_2_1 18/12/2022
重现 DF1
和 DF2
的代码:
DF1= data.frame(
stringsAsFactors = FALSE,
ID = c("id1","id1","id1","id1",
"id1","id2","id2","id2","id2"),
date1 = c("1/1/2020","2/1/2020",
"17/1/2020","20/1/2020","21/1/2020","21/12/2022",
"22/12/2022","18/12/2022","19/12/2022"),
param = c("pA", "pA", "pA", "pB", "pB", "pA", "pA", "pB", "pB"),
value = c("pA_1_1","pA_1_2","pA_1_3",
"pB_1_1","pB_1_2","pA_2_1","pA_2_2","pB_2_1","pB_2_2")
)
DF2=data.frame(
stringsAsFactors = FALSE,
ID = c("id1", "id2"),
date2 = c("15/1/2020", "20/12/2020")
)
这是我的解决方案。我确定有一种方法可以用更少的代码编写它(使用一个数据帧而不是两个数据帧,然后再合并)。但是我现在还不知道。
library(tidyverse)
library(lubridate)
# Get before date2
before <- DF1 %>%
left_join(DF2,by = "ID") %>%
mutate(diff = dmy(date1)-dmy(date2)) %>%
mutate(Grp = data.table::rleid(param)) %>%
filter(diff < 0) %>%
group_by(Grp) %>%
filter(diff == max(diff)) %>%
ungroup
# Get after date2
after <- DF1 %>%
left_join(DF2,by = "ID") %>%
mutate(diff = dmy(date1)-dmy(date2)) %>%
mutate(Grp = data.table::rleid(param)) %>%
filter(diff > 0) %>%
group_by(Grp) %>%
filter(! Grp %in% before$Grp, diff == min(diff)) %>%
ungroup
result <- bind_rows(before,after) %>%
select(ID,date2, param, value, date1) %>%
arrange(ID, param)
说明:我正在使用 lubridate 库来比较日期。我执行相同的过程来创建两个数据帧 - 第一个(在 df 之前)用于完成第一个条件的组(DF1 中最近的日期在 DF2 中的 date2 之前),第二个(在 df 之后)用于相反方向的组(最近的DF1 中的日期在 DF2 中的 date2 之后)。
我先解释一下:
# Get before date2
before <- DF1 %>%
left_join(DF2,by = "ID") %>%
mutate(diff = dmy(date1)-dmy(date2)) %>%
mutate(Grp = data.table::rleid(param)) %>%
filter(diff < 0) %>%
group_by(Grp) %>%
filter(diff == max(diff)) %>%
ungroup
在这里,我们通过ID合并DF1和DF2,因此具有相同ID的行具有相同的date2。然后,我们计算 date1-date2 的差异 - 首先我们使用 dmy()
将字符转换为日期。因此,date2 之前的日期将是负差异。使用 data.table::rleid(param)
我们枚举具有不同 ID 和参数的子组,因此我们可以知道子组。然后我们可以按 then 分组并按它们过滤。
最后:
result <- bind_rows(before,after) %>%
select(ID,date2, param, value, date1) %>%
arrange(ID, param)
我们按行绑定两个数据框,select 您要查找的列,以删除我们创建的用于操作的列(组和过滤器)。 PS:我添加了 arrange() 以确保最终的 df 按 ID 和参数值排序。