假设我有两个数据帧。
第一个包括“日期”,其中“姓名”为“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属于相应的日期范围。
有人可以帮我吗?
答案 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
)位于Date
和Stop.Date
(来自df
),Date <= Date1 < Stop.Date
之间。由于有许多可能的匹配,我们需要使用allow.cartesian = TRUE
。
useR有一个video of Arun's talk! 2016年国际R用户大会使用data.table 介绍高效的内存中非等连接。