这里有一个简单的例子来说明我的问题: 我有两个数据表(data.table对象),一个非常大的表,表A,有400万个产品,它们记录在日期并且有 ex(盗版)日期< / em>的。在这两个日期期间,如果产品的期限涵盖某个 payment_date ,产品将支付某个金额,后两个变量将在第二个表B中收集。
表A的负责人:
date exdate unique_id
1: 1999-01-04 1999-09-18 294
2: 1999-01-04 1999-09-18 295
3: 1999-01-04 1999-09-18 296
4: 1999-01-04 1999-09-18 297
5: 1999-01-04 1999-09-18 298
6: 1999-01-05 1999-09-18 299
表B的负责人:
payment_date amount
1: 1998-06-30 4.18
2: 1998-09-30 4.26
3: 1998-12-31 4.00
4: 1999-03-31 4.01
5: 1999-06-30 4.18
6: 1999-09-30 4.45
重要的是,表A中的产品具有不同的期间长度,因此对于一些产品有多个付款日期,而有些则没有(日期在%Y%M%D)。
我现在想要收集A中所有金额和付款日期的每个产品,直到其到期日为止。当然,这可以通过for循环来实现,但是考虑到巨大的表格,这非常讨厌。因此,我想使用更快的data.table方法。
现在,以下内容为金额提供了技巧:
tmp <- B[A,on=.(payment_date>date, payment_date<=exdate),.(amount,unique_id,payment_date),by=.EACHI]
colnames(tmp)<-c("date","exdate","amount","unique_id","payment_date")
输出如下:
date exdate amount unique_id payment_date
1: 1999-01-04 1999-09-18 4.01 294 1999-03-31
2: 1999-01-04 1999-09-18 4.18 294 1999-03-31
3: 1999-01-04 1999-09-18 4.01 295 1999-03-31
4: 1999-01-04 1999-09-18 4.18 295 1999-03-31
5: 1999-01-04 1999-09-18 4.01 296 1999-03-31
6: 1999-01-04 1999-09-18 4.18 296 1999-03-31
7: 1999-01-04 1999-09-18 4.01 297 1999-03-31
8: 1999-01-04 1999-09-18 4.18 297 1999-03-31
9: 1999-01-04 1999-09-18 4.01 298 1999-03-31
我的问题是data.table只给我每个金额的第一个payment_date,所以尽管这些产品在其生命周期中明显有两个付款日期,但我只得到(1999-03-31,1999-03-31),而不是(1999-03-31,1999-06-30)。
是否有人知道我如何告诉data.table为我提供金额和payment_dates的相应向量,而不仅仅是每个产品的金额和payment_dates向量的第一个元素?
我希望这个例子涵盖了我的整个斗争,如果还需要更多东西让事情更清楚,请告诉我。任何帮助都非常感谢。
P.S:当然我也尝试了sapply(),但是像往常一样,它就像for循环一样,并且与data.table方法相比不会节省太多时间。
答案 0 :(得分:2)
奇怪,但如果将一份payment_date添加到B似乎正常工作
let
答案 1 :(得分:1)
A <- structure(list(date = structure(c(10595, 10595, 10595, 10595,
10595, 10596), class = "Date"), exdate = structure(c(10852, 10852,
10852, 10852, 10852, 10852), class = "Date"), unique_id = 294:299), class = "data.frame", .Names = c("date",
"exdate", "unique_id"), row.names = c(NA, -6L))
B <- structure(list(payment_date = structure(c(10407, 10499, 10591,
10681, 10772, 10864), class = "Date"), amount = c(4.18, 4.26,
4, 4.01, 4.18, 4.45)), class = "data.frame", .Names = c("payment_date",
"amount"), row.names = c(NA, -6L))
您可以使用tidyr:nest
和purrr:map
来完成此操作。 dplyr:between
是x >= left_arg & x <= right_arg
library(tidyverse)
A %>%
mutate(copy1=date, copy2=exdate) %>%
nest(copy1, copy2) %>% # nest copies of date and exdate
mutate(data = map(data, ~B %>% filter(between(payment_date, .x$copy1, .x$copy2)))) %>% # filter B where payment_date is between date and ex_date of A[row,]
unnest(data)
date exdate unique_id payment_date amount
<date> <date> <int> <date> <dbl>
1 1999-01-04 1999-09-18 294 1999-03-31 4.01
2 1999-01-04 1999-09-18 294 1999-06-30 4.18
3 1999-01-04 1999-09-18 295 1999-03-31 4.01
4 1999-01-04 1999-09-18 295 1999-06-30 4.18
5 1999-01-04 1999-09-18 296 1999-03-31 4.01
6 1999-01-04 1999-09-18 296 1999-06-30 4.18
7 1999-01-04 1999-09-18 297 1999-03-31 4.01
8 1999-01-04 1999-09-18 297 1999-06-30 4.18
9 1999-01-04 1999-09-18 298 1999-03-31 4.01
10 1999-01-04 1999-09-18 298 1999-06-30 4.18
11 1999-01-05 1999-09-18 299 1999-03-31 4.01
12 1999-01-05 1999-09-18 299 1999-06-30 4.18