簡體   English   中英

R-基於最近日期合並數據框

[英]R- merge dataframes based on recent dates

我有兩個數據框:

在 DF1 中,對於每個IDparam都記錄在不同的日期。 在 DF2 中,對於每個ID ,都會給出多個日期。 對於每個ID ,我想從 DF1 中獲取所有相應的paramvalue ,具體取決於日期:對於給定參數,或者與date2 (在DF2中)之前的最新date1 (在DF1中)相對應的value ,或者如果有沒有這樣的date1date2之后的最新value

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

重現DF1DF2的代碼:

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")
)

這是我的解決方案。 我確信有一種方法可以用更少的代碼編寫這個(使用一個 dataframe 而不是兩個和以后合並)。 但我現在不知道。

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 和參數的子組,因此我們可以知道子組。 然后我們可以按那時分組並按它們過濾。

在最后:

result <- bind_rows(before,after) %>% 
  select(ID,date2, param, value, date1) %>%
  arrange(ID, param)

我們按行綁定兩個 dataframe 和 select 您要查找的列,以刪除我們創建用於操作的列(組和過濾器)。 PS:我添加了安排()以確保最終的 df 按 ID 和參數值排序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM