如果日期在日期范围

时间:2018-04-05 00:08:08

标签: r dplyr data.table sumifs non-equi-join

假设我有两个数据帧。

第一个包括“日期”,其中“姓名”为“ID”发出“Rec”,而“Stop.Date”则“Rec”变为无效。

df(仅限部分)

structure(list(Date = structure(c(13236, 13363, 14074, 13199, 
14554), class = "Date"), ID = c("AU0000XINAA9", "AU0000XINAA9", 
"AU0000XINAC5", "AU0000XINAI2", "AU0000XINAJ0"), Name = c("N+1 BREWIN", 
"N+1 BREWIN", "ARBUTHNOT SECURITIES LTD.", "INVESTEC BANK (UK) PLC", 
"AWRAQ INVESTMENTS"), Rec = c(1, 2, 2, 2, 1), Stop.Date = structure(c(13363, 
13509, 14937, 13230, 16702), class = "Date")), .Names = c("Date", 
"ID", "Name", "Rec", "Stop.Date"), class = c("data.table", "data.frame"
), row.names = c(NA, -5L))

第二个数据帧只包含一个时间序列:在本案例中,我们可以说是从2006年3月29日到2006年底。

DF2

      Date1
  1: 2006-02-20
  2: 2006-02-21
  3: 2006-02-22
  4: 2006-02-23
  5: 2006-02-24
 ---           
311: 2006-12-27
312: 2006-12-28
313: 2006-12-29
314: 2006-12-30
315: 2006-12-31

如果df2中的“Date1”变量落在时间范围内(Date,直到Stop.Date),我希望我的代码将所有“Rec”加上ID和Name的总和。

我发现这篇文章R - If date falls within range, then sum并且它似乎非常接近我的问题,但解决方案不考虑任何组。

我想提出一个data.frame,其中对于 df2 中的每个日期,显示每个“ID”的“REC”总和。

预期输出,例如

        Date1         ID          SumRec 

    1 2006-02-20 AU0000XINAI2        2
    2 2006-02-21 AU0000XINAI2        2
...
    4 2006-03-29 AU0000XINAA9        1
    5 2006-03-30 AU0000XINAA9        1
    6 2006-08-03 AU0000XINAA9        2  # since Date1 2006-08-03 is at the end 
                                          of range in df (row#1)-> it falls 
                                          within range in df (row#2) 
...

请记住,这只是数据的一小部分。通常,对于来自不同“名称”的每个“ID”,存在更多的Rec。 (然后sum函数才有意义)

非常感谢您的帮助。

更新版本

新数据框:

DF

structure(list(Date = structure(c(9905, 10381, 10381, 10954, 
10584, 10632, 10778, 10520, 10631, 10905), class = "Date"), ID = c("BMG4593F1389", 
"BMG4593F1389", "BMG4593F1389", "BMG4593F1389", "BMG4593F1389", 
"BMG4593F1389", "BMG4593F1389", "BMG526551004", "BMG526551004", 
"BMG526551004"), Name = c("ING FM", "Permission Denied 128064", 
"Permission Denied 2880", "Permission Denied 2880", "Permission Denied 32", 
"Permission Denied 888", "Permission Denied 888", "Permission Denied 2880", 
"Permission Denied 2880", "Permission Denied 2880"), Rec = c(2, 
3, 2, 2, 3, 3, 3, 1, 3, 3), Stop.Date = structure(c(12095, 11232, 
10954, 11180, 11345, 10764, 11667, 10631, 10905, 11087), class = "Date")), .Names = c("Date", 
"ID", "Name", "Rec", "Stop.Date"), class = c("data.table", "data.frame"
), row.names = c(NA, -10L))

DF2

structure(list(Date1 = structure(c(10954, 10955, 10956, 10957, 
10958, 10959), class = "Date")), .Names = "Date1", row.names = c(NA, 
-6L), class = c("data.table", "data.frame"))

如果我现在执行以下代码:

> df=df[,interval := interval(df$Date, df$Stop.Date)]
> 
> df1 <- do.call(rbind, lapply(df2$Date1, function(x){   index <- x
> %within% df$interval;   list(ID = ifelse(any(index), df$ID[index],
> NA), Rec = ifelse(any(index), df$Rec[index], NA), 
>        Name = ifelse(any(index), df$Name[index], NA),interval = ifelse(any(index),df$interval[index],NA))})) 
> 
> df3 <- cbind(df2, df1)

我想出了以下结果:

     Date1        ID        Rec  Name interval
1: 1999-12-29 BMG4593F1389   2 ING FM 189216000
2: 1999-12-30 BMG4593F1389   2 ING FM 189216000
3: 1999-12-31 BMG4593F1389   2 ING FM 189216000
4: 2000-01-01 BMG4593F1389   2 ING FM 189216000
5: 2000-01-02 BMG4593F1389   2 ING FM 189216000
6: 2000-01-03 BMG4593F1389   2 ING FM 189216000

但是因为例如df $ ID“BMG4593F1389”的df2 $ Date1(“1999-12-29”)属于df中6个条目的日期范围(对于不同的df $ Names)对于这个特定的df $ date1应该是:

日期1999-12-29的预期结果(为简单起见,此处忽略了df3 $ interval变量)

         Date1        ID        Rec         Name 
    1: 1999-12-29 BMG4593F1389   2   ING FM 
    2: 1999-12-29 BMG4593F1389   3   Permission Denied 128064 
    3: 1999-12-29 BMG4593F1389   2   Permission Denied 2880
    4: 1999-12-29 BMG4593F1389   3   Permission Denied 32
    5: 1999-12-29 BMG4593F1389   3   Permission Denied 888

    6: 1999-12-29 BMG5265510042  3   Permission Denied 2880

    7: 1999-12-30 BMG4593F1389   2   ING FM
... etc

所以最后我需要复制df $ Date1中的日期,如果多个名称为特定的df $ ID发出Rec,该ID属于相应的日期范围。

有人可以帮我吗?

1 个答案:

答案 0 :(得分:0)

如果我正确理解问题的更新版本,可以使用 non-equi join 和后续聚合来解决这个问题:

library(data.table)
# non-equi join
df[df2, on = .(Date <= Date1, Stop.Date > Date1), allow = TRUE][
  # aggregation
  , .(sumRec = sum(Rec)), by = .(Date, ID, Name)]
          Date           ID                     Name sumRec
 1: 1999-12-29 BMG4593F1389                   ING FM      2
 2: 1999-12-29 BMG4593F1389 Permission Denied 128064      3
 3: 1999-12-29 BMG4593F1389   Permission Denied 2880      2
 4: 1999-12-29 BMG4593F1389     Permission Denied 32      3
 5: 1999-12-29 BMG4593F1389    Permission Denied 888      3
 6: 1999-12-29 BMG526551004   Permission Denied 2880      3
 7: 1999-12-30 BMG4593F1389                   ING FM      2
 8: 1999-12-30 BMG4593F1389 Permission Denied 128064      3
 9: 1999-12-30 BMG4593F1389   Permission Denied 2880      2
10: 1999-12-30 BMG4593F1389     Permission Denied 32      3
11: 1999-12-30 BMG4593F1389    Permission Denied 888      3
12: 1999-12-30 BMG526551004   Permission Denied 2880      3
13: 1999-12-31 BMG4593F1389                   ING FM      2
14: 1999-12-31 BMG4593F1389 Permission Denied 128064      3
15: 1999-12-31 BMG4593F1389   Permission Denied 2880      2
16: 1999-12-31 BMG4593F1389     Permission Denied 32      3
17: 1999-12-31 BMG4593F1389    Permission Denied 888      3
18: 1999-12-31 BMG526551004   Permission Denied 2880      3
19: 2000-01-01 BMG4593F1389                   ING FM      2
20: 2000-01-01 BMG4593F1389 Permission Denied 128064      3
21: 2000-01-01 BMG4593F1389   Permission Denied 2880      2
22: 2000-01-01 BMG4593F1389     Permission Denied 32      3
23: 2000-01-01 BMG4593F1389    Permission Denied 888      3
24: 2000-01-01 BMG526551004   Permission Denied 2880      3
25: 2000-01-02 BMG4593F1389                   ING FM      2
26: 2000-01-02 BMG4593F1389 Permission Denied 128064      3
27: 2000-01-02 BMG4593F1389   Permission Denied 2880      2
28: 2000-01-02 BMG4593F1389     Permission Denied 32      3
29: 2000-01-02 BMG4593F1389    Permission Denied 888      3
30: 2000-01-02 BMG526551004   Permission Denied 2880      3
31: 2000-01-03 BMG4593F1389                   ING FM      2
32: 2000-01-03 BMG4593F1389 Permission Denied 128064      3
33: 2000-01-03 BMG4593F1389   Permission Denied 2880      2
34: 2000-01-03 BMG4593F1389     Permission Denied 32      3
35: 2000-01-03 BMG4593F1389    Permission Denied 888      3
36: 2000-01-03 BMG526551004   Permission Denied 2880      3
          Date           ID                     Name sumRec

请注意,我在df中直接使用structure(...)时遇到了一条奇怪的错误消息。调用

后,错误消息消失了
df <- as.data.table(df)

解释

asked解释非equi join 是如何工作的。 非等联接data.table联接的扩展。 data.table是一个增强基础R data.frame的包。

在这里,我们将df2加入df,即我们希望在结果df2中看到所有df行匹配,但只有Date1 {1}}(来自df2)位于DateStop.Date(来自df),Date <= Date1 < Stop.Date之间。由于有许多可能的匹配,我们需要使用allow.cartesian = TRUE

useR有一个video of Arun's talk! 2016年国际R用户大会使用data.table 介绍高效的内存中非等连接。