【问题标题】:Matching date range from to different data frames in R匹配日期范围从R中的不同数据框
【发布时间】:2021-10-17 11:07:06
【问题描述】:

我现在正在努力寻找一种方法来匹配 R 中两个不同的表(行号不平衡)与匹配的日期范围。

第一个数据框表示某人已声明的内容,第二个数据框表示实际情况。问题是一个 id 说 A 可能在他/她的存储空间中保存了一周或更长时间的公斤数产品然后一周后出现。

所以我有两个不同行的数据框。两个行数都超过 500.000。第一个有 500.000,第二个有 520.000。(因此可能会出现一些 NA,但这没关系)。

我想从这 2 个不同的数据帧中查找和匹配:

  1. id 相同,
  2. 产品代码和人代码要一致,并且
  3. 检查第二个数据框中的日期是否在第一个数据框中的日期一个月的范围内(例如他/她在2020/1/1申报体重(100公斤)并出现2020/1/15,但实际重量为105)。

如果所有这些条件都为真,则将两个权重相加(来自数据帧 1 和 2)

所需的输出必须是具有匹配 id、日期范围、product、man、2 列权重的数据框,最后一列是权重总和的值。

示例数据框是以下 R 中的两个数据框:


id = rep("A",10)
date = seq(as.Date("2000/1/1"), by = "day", length.out = 10)
product = c("E1","E1","E2","E3","E3","E4","E1","E1","E5","E5")
man = c("PS","PS","PS","DDR","DDR","FFR","PS","PS","BA","BA")
weight = c(1505,300,259,231,140,150,300,112,203,2200) 
data1 = data.frame(id,date,product,man,weight);data1


id2 = rep("A",10)
date2 = sample(seq(as.Date("2000/1/10"), by = "day", length.out = 10),10)
product2 = c("E3","E3","E1","E1","E1","E1","E5","E4","E5","E2")
man2 = c("DDR","DDR","PS","PS","PS","PS","BA","FFR","BA","PS")
weight2 = c(259,295,260,240,135,145,250,110,2000,210) 
data2 = data.frame(id2,date2,product2,man2,weight2);data2

如何将它们与轧花日期延迟条件相匹配?

有什么帮助吗?

【问题讨论】:

    标签: r dataframe date if-statement join


    【解决方案1】:

    不确定是不是你想要的,但它看起来像一个滚动连接...

    使用 data.table 和 lubridate 包,一个版本可能是:

    (这里我举两个例子,一个提前 30 天,一个提前一个月)

    set.seed(0)
    
    id = rep("A",10)
    date = seq(as.Date("2000/1/1"), by = "day", length.out = 10)
    product = c("E1","E1","E2","E3","E3","E4","E1","E1","E5","E5")
    man = c("PS","PS","PS","DDR","DDR","FFR","PS","PS","BA","BA")
    weight = c(1505,300,259,231,140,150,300,112,203,2200) 
    data1 = data.frame(id,date,product,man,weight);data1
    
    
    id2 = rep("A",10)
    date2 = sample(seq(as.Date("2000/1/10"), by = "day", length.out = 10),10)
    product2 = c("E3","E3","E1","E1","E1","E1","E5","E4","E5","E2")
    man2 = c("DDR","DDR","PS","PS","PS","PS","BA","FFR","BA","PS")
    weight2 = c(259,295,260,240,135,145,250,110,2000,210) 
    data2 = data.frame(id2,date2,product2,man2,weight2);data2
    
    require(data.table)
    require(lubridate)
    
    setDT(data1)
    setkey(data1)
    setDT(data2)
    setkey(data2)
    
    data1[, weight_p50 := weight + 50]
    data1[, weight_m50 := weight - 50]
    
    
    data1[, date := as.Date(date)]
    data2[, date2 := as.Date(date2)]
    data1[, date_plus_one_month := as.Date(ymd(date %m+% months(1)))]
    data1[, date_plus_30_days := as.Date(date + days(30))]
    
    data2[, date2_ := date2]
    data1[, date_ := date]
    
    res <-
        data1[data2, list(id, product, man, date = date_, date2, weight, weight2, total_weight = weight + weight2),
              on = .(id = id2,
                     product = product2,
                     man = man2, 
                     date_plus_30_days >= date2, 
                     date <= date2_,
                     weight_p50 >= weight2,
                     weight_m50 <= weight2),
              allow.cartesian = TRUE, nomatch = 0
        ][][]
    setkey(res, id, product, man, date, date2)
    res <- unique(res, by = c("id", "product", "man"))
    res[]
    
    
    

    给出:

       id product man       date      date2 weight weight2 total_weight
    1:  A      E1  PS 2000-01-02 2000-01-16    300     260          560
    2:  A      E2  PS 2000-01-03 2000-01-17    259     210          469
    3:  A      E3 DDR 2000-01-04 2000-01-18    231     259          490
    4:  A      E4 FFR 2000-01-06 2000-01-19    150     110          260
    5:  A      E5  BA 2000-01-09 2000-01-12    203     250          453
    

    编辑:在 OP cmets 之后,我在 id x man x product 上添加了唯一性,以便它只保留满足约束的第一个日期。

    【讨论】:

    • 它非常接近我想要的,但我不想再次搜索并匹配其他值。就像我想要你的结果的 unique() 一样
    • 基本上只打印第一个匹配项。即第 1、9、11 行等。
    • 我认为您的示例很难理解,例如在我的 data1 代码中,A/E1/PS 有 4 个日期(行),日期为 2000-01-01/02/07/日期为 2000-01-10/11/14/16 的 data2 中的 08 和 4 哪些行应该匹配并保留在最终结果中?你想在每个数据框中只保留第一个日期吗?还是在每个 data.frame 中聚合? (在这里我报告了所有匹配项(A/E1/PS 为 4x4=16),对于 id x man x product 的组合,日期在 data1 中可能是唯一的?
    • 根据权重 1,必须保留权重 2 附近的权重值。我已经在我的真实数据集中实现了您的代码,并且与您的答案相同,但我只需要附近的 + - 50 重量2
    • 这还不清楚。您说保留第 1 行,但重量相差不小于 50?还是你的意思是 50%?
    猜你喜欢
    • 1970-01-01
    • 2019-07-02
    • 1970-01-01
    • 2018-11-07
    • 1970-01-01
    • 2018-08-06
    • 1970-01-01
    • 2016-01-14
    • 2020-08-07
    相关资源
    最近更新 更多