如何使用R查找矩阵A的特定日期之前的最接近日期?在特定日期之后的14天?

时间:2018-08-10 02:55:45

标签: r date

我是R中的新手。 我有两个数据集A和B。

A <- data.table::fread(
"
V1  DATE    ID
1   7/16/11 a
2   2/18/09 b
3   3/25/08 c
")

B <- data.table::fread(
"
V1  DATE    ID  Value
1   2013-06-13  a   109
2   2017-08-22  a   86
3   2017-09-15  a   88
4   2008-11-05  a   78
5   2009-02-17  a   74
6   2009-03-09  a   84
7   2009-03-17  a   81
8   2009-04-14  a   57
9   2009-04-21  a   65
10  2009-05-12  a   54
11  2009-06-08  a   54
12  2009-08-27  a   68
13  2011-08-26  b   199
14  2011-12-07  b   174
15  2012-01-31  b   66
16  2012-02-15  b   58
17  2012-04-17  b   59
18  2012-12-21  b   78
19  2013-01-14  b   91
20  2014-03-12  b   74
21  2014-08-28  b   98
22  2014-10-18  b   112
23  2010-12-15  b   36
24  2011-08-26  b   199
25  2011-12-07  b   174
26  2012-01-31  b   66
27  2012-02-15  b   58
28  2012-04-17  b   59
29  2015-05-08  c   105
30  2006-03-27  c   69
31  2007-03-12  c   104
32  2007-11-09  c   63
33  2008-03-25  c   239
34  2008-04-04  c   446
35  2008-04-09  c   354
36  2008-04-10  c   365
37  2008-04-11  c   366
38  2008-04-18  c   273
39  2008-04-28  c   271
40  2008-05-06  c   262
41  2008-05-19  c   72
42  2008-05-24  c   86
43  2008-06-20  c   47
44  2008-07-10  c   46
45  2008-08-06  c   55
46  2008-09-01  c   58
47  2008-09-29  c   56
48  2008-10-30  c   53
49  2008-12-09  c   71
50  2008-12-18  c   63
51  2009-01-14  c   60
52  2009-02-21  c   58
53  2009-03-28  c   54
54  2009-04-29  c   56
55  2009-04-30  c   59
56  2009-06-23  c   64
57  2009-07-24  c   69
58  2009-08-17  c   73
59  2009-10-04  c   127
60  2009-11-26  c   289
61  2009-12-02  c   277
62  2009-12-08  c   230
")

我尝试了数周的时间来使用R:

  1. 从B中查找ID==A$IDB$DATE是最接近日期{em>之前的日期或与A$DATE相同的日期的值;
    预期的结果是:ID=c, DATE=2008-03-25, Value=239

  2. 从B中找到ID==A$IDB$DATE的值是A$DATE之后的14天。如果14天后没有确切的日期,请找到最接近的日期值(例如, A$DATE之后的15、16或17天)
    预期的结果是:ID=c, DATE=2008-04-09, Value=354

2 个答案:

答案 0 :(得分:1)

两个问题都可以通过data.table中的滚动连接来回答。

但是,准备数据有两个重要步骤。

  1. 日期字符串需要转换为类IDate(或Date),以允许进行日期算术。 (IDate使用整数表示来节省内存)。
  2. 需要将数据帧强制转换为data.table以启用增强的语法。 setDT()强制通过引用将数据框或小标题强制为data.table ,即不进行复制。
    顺便说一句:OP提供的样本数据集已经是data.tables,因为OP使用了data.table::fread()函数。

数据准备:

library(data.table)
setDT(A)[, DATE := as.IDate(DATE, "%m/%d/%y")]
setDT(B)[, DATE := as.IDate(DATE)]

现在,我们可以应用滚动加入

B[A, on = .(ID, DATE), roll = +Inf, .(ID, DATE, Value)]
   ID       DATE Value
1:  a 2011-07-16    68
2:  b 2009-02-18    NA
3:  c 2008-03-25   239

可以通过以正确的顺序B打印B[order(ID, DATE)]来验证结果。 ID == "b"B的最早日期是2011-08-26。因此,B中的日期 2009-02-18之前或之前。

请注意,DATE列中的值是参考日期A$DATE不是匹配的B$DATE


在OP明确预期结果后,

编辑

第二个问题也可以用rolling join解决,但是代码需要进行三处修改:

  1. 参考日期A$DATE需要移14天。
  2. 我们需要进行后退滚动连接,因为OP希望在B中找到已转换参考日期或之后的最近日期。
  3. 根据OP的预期结果,结果应包含匹配的B$DATE

有了其他要求,我们得到

B[A[, .(ID, DATE = DATE + 14)], on = .(ID, DATE), roll = -Inf, .(ID, DATE = x.DATE, Value)]
   ID       DATE Value
1:  a 2013-06-13   109
2:  b 2010-12-15    36
3:  c 2008-04-09   354

答案 1 :(得分:0)

使用dplyr的解决方案:

q1和q2对应于您的两个问题。

library(dplyr)

A$DATE <- as.Date(A$DATE,format = "%m/%d/%y")

B$DATE <- as.Date(B$DATE)

BA <- left_join(B,A, by= c("ID"="ID"))

q1 <- BA %>%
  filter(ID %in% A$ID) %>%
  filter(DATE.x < DATE.y) %>%
  group_by(ID) %>%
  arrange(desc(DATE.x)) %>%
  slice(1)

q2 <- BA %>%
  filter(ID %in% A$ID) %>%
  group_by(ID) %>%
  filter(as.numeric(DATE.x) - as.numeric(DATE.y) >= 14)

q1
#> # A tibble: 2 x 6
#> # Groups:   ID [2]
#>    V1.x DATE.x     ID    Value  V1.y DATE.y    
#>   <int> <date>     <chr> <int> <int> <date>    
#> 1    12 2009-08-27 a        68     1 2011-07-16
#> 2    32 2007-11-09 c        63     3 2008-03-25

q2
#> # A tibble: 48 x 6
#> # Groups:   ID [3]
#>     V1.x DATE.x     ID    Value  V1.y DATE.y    
#>    <int> <date>     <chr> <int> <int> <date>    
#>  1     1 2013-06-13 a       109     1 2011-07-16
#>  2     2 2017-08-22 a        86     1 2011-07-16
#>  3     3 2017-09-15 a        88     1 2011-07-16
#>  4    13 2011-08-26 b       199     2 2009-02-18
#>  5    14 2011-12-07 b       174     2 2009-02-18
#>  6    15 2012-01-31 b        66     2 2009-02-18
#>  7    16 2012-02-15 b        58     2 2009-02-18
#>  8    17 2012-04-17 b        59     2 2009-02-18
#>  9    18 2012-12-21 b        78     2 2009-02-18
#> 10    19 2013-01-14 b        91     2 2009-02-18
#> # ... with 38 more rows