【问题标题】:mapping based on nearest date基于最近日期的映射
【发布时间】:2017-09-11 15:47:58
【问题描述】:

我想获取具有关联“所有者”和日期的电子邮件列表,并将它们与传入的订单、日期和值进行匹配。匹配键是电子邮件,但我希望它在最近的日期匹配,因为在某些情况下,电子邮件地址可能有 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 中添加一列,以固定正确的“所有者”,即拥有该电子邮件地址的人和 em> 最接近日期。

想要的结果:

> 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 个示例中的其他所有者。

感谢您的帮助!

【问题讨论】:

    标签: r join dplyr left-join


    【解决方案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 选择绝对日期最小的记录。

    【讨论】:

    • 很好 - 我认为这是我的想法自然会去的地方,尽管我应该了解更多关于滚动连接的信息。切片通常做什么?我会用 filter(!duplicated(e)) 交换切片,它会在对升序 Date_ABS_Diff 进行排序后抓住第一个切片
    • @MattW。 slice 按位置选择行。请参阅文档:rdocumentation.org/packages/dplyr/versions/0.7.3/topics/slice
    • 啊完美。非常感谢!学到了一些新东西。
    【解决方案2】:

    这是 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 没有滚动连接,也永远不会有更新连接,所以那里没有类似物。

    【讨论】:

    • 非常感谢弗兰克!我记得过去使用 data.table 学习滚动连接,但我更喜欢 dplyr,因为它更容易学习。我会实现这个,让你知道它是怎么回事! - 快速问:-Inf 调用是最接近的吗?还是从一侧寻找最近的,更早还是更晚?
    • 我还有一个要求。当我查看这些时,我想做最接近的日期,这意味着迄今为止距离的绝对值。从日期开始可以是过去或未来。我将如何调整 roll 参数以匹配它?
    • @MattW 在?data.table 中,记录了roll= 参数的值。我认为roll="nearest" 会做你想做的事。
    猜你喜欢
    • 2021-12-07
    • 1970-01-01
    • 1970-01-01
    • 2022-01-03
    • 2017-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多