基于最近日期的映射

时间:2017-09-11 15:47:59

标签: r join dplyr left-join

我想列出一个包含关联“所有者”和日期的电子邮件列表,并将其与传入的订单进行匹配,并附上日期和值。匹配的密钥是电子邮件,但我希望它匹配最近的日期,因为在某些情况下,电子邮件地址可能有2个不同的所有者。

可重复的例子:

require(dplyr)

e <- c("e3r@gmail.com", "e3r@gmail.com", "poi@aol.com", "tyu@gmail.com", "poi@aol.com", "tyu@gmail.com")
d <- c("2017-01-01", "2017-04-05", "2017-04-12", "2017-05-05", "2017-08-05", "2017-12-05")
p <- c("Jeff", "Sam", "Sam", "Jeff", "Matt", "Matt")
df <- data_frame(e, d, p) %>% mutate(d=as.Date(d))

o <- c("e3r@gmail.com", "poi@aol.com", "sdf@gmail.com", "tyu@gmail.com")
d2 <- c("2017-02-02", "2017-04-28", "2017-05-05", "2017-07-01")
a <- c(600.50, 3000, 4999.99, 2050.6)
df2 <- data_frame(o, d2, a) %>% mutate(d2 = as.Date(d2))

第一个df是电子邮件地址的地图归p人所有。 df2是这些电子邮件地址附带的订单,我想在df2添加一个列,其中包含正确的“所有者”,无论谁拥有分配给他们的电子邮件地址的日期最接近。

期望的结果:

> df2
# A tibble: 4 x 3
              o         d2       a       newowner
          <chr>     <date>   <dbl>       <char>
1 e3r@gmail.com 2017-02-02  600.50       "Jeff"
2   poi@aol.com 2017-04-28 3000.00       "Sam"
3 sdf@gmail.com 2017-05-05 4999.99       NA
4 tyu@gmail.com 2017-07-01 2050.60       "Jeff"

目前,这不是一个大问题 - 在“拥有”电子邮件地址的70k记录中,只有约86个重复案例。但是,所有权在一年的最后几个月都在发生变化,因此如果所有权转移,可能会引入大量重复。我目前正在从最远的日期开始接收所有者,并在这86个例子中覆盖其他所有者。

感谢您的帮助!

2 个答案:

答案 0 :(得分:6)

这是data.table中的标准滚动更新连接:

library(data.table)
DT = data.table(df)
DT2 = data.table(df2)
DT2[DT, on=.(o = e, d2 = d), roll=-Inf, v := i.p ]

               o         d2       a    v
1: e3r@gmail.com 2017-02-02  600.50 Jeff
2:   poi@aol.com 2017-04-28 3000.00  Sam
3: sdf@gmail.com 2017-05-05 4999.99   NA
4: tyu@gmail.com 2017-07-01 2050.60 Jeff

如果根据标题,您想要最近的匹配,请使用roll = "nearest"代替roll = -Inf

Dplyr没有滚动连接,并且永远不会有更新连接,所以那里没有类似的东西。

答案 1 :(得分:1)

@Frank的答案很棒,就像他说的那样,data.table有滚动连接但dplyr没有。所以我认为data.table在这里是更好的选择。但是,如果你想留在dplyr。这是一个想法。

library(dplyr)
df3 <- df %>%
  full_join(df2, by = c("e" = "o")) %>%
  mutate(Date_ABS_Diff = abs(d - d2)) %>%
  arrange(e, Date_ABS_Diff) %>%
  group_by(e) %>%
  slice(1) %>%
  select(o = e, d2, a, newowner = p)
df3
# A tibble: 4 x 4
# Groups:   o [4]
              o         d2       a newowner
          <chr>     <date>   <dbl>    <chr>
1 e3r@gmail.com 2017-02-02  600.50     Jeff
2   poi@aol.com 2017-04-28 3000.00      Sam
3 sdf@gmail.com 2017-05-05 4999.99     <NA>
4 tyu@gmail.com 2017-07-01 2050.60     Jeff

此方法使用full_join通过电子邮件组合所有可能的组合。之后,计算日期之间的绝对差异,并使用arrangeslice选择具有最小绝对日期的记录。