【问题标题】:Join with fuzzy matching by date in R在R中按日期加入模糊匹配
【发布时间】:2020-12-25 10:25:23
【问题描述】:

我有两个数据框,我想按日期加入它们

df1 <-
  data.frame(
    day = seq(ymd("2020-01-01"), ymd("2020-01-14"), by = "1 day"),
    key = rep(c("green", "blue"), 7),
    value_x = sample(1:100, 14)
  ) %>% 
    as_tibble()

df2 <-
  data.frame(
    day = seq(ymd("2020-01-01"), ymd("2020-01-12"), by = "3 days"),
    key = rep(c("green", "blue"), 2),
    value_y = c(2, 4, 6, 8)
  ) %>% 
  as_tibble()

我希望输出是这样的

# A tibble: 14 x 3
   day        key   value_x   value_y
   <date>     <fct>   <int>     <int>
 1 2020-01-01 green      91         2
 2 2020-01-02 blue       28        NA
 3 2020-01-03 green      75         2
 4 2020-01-04 blue       14         4
 5 2020-01-05 green       3         2
 6 2020-01-06 blue       27         4
 7 2020-01-07 green      15         6
 8 2020-01-08 blue        7         4
 9 2020-01-09 green       1         6
10 2020-01-10 blue       10         8
11 2020-01-11 green       9         6
12 2020-01-12 blue       76         8
13 2020-01-13 green      31         6
14 2020-01-14 blue       62         8

我试着做这个代码

merge(df1, df2, by = c("day", "key"), all.x = TRUE)

我希望将左表中的日期连接到 Y 表中具有值的最近一天。如果没有值,那么应该是NA。

编辑 --

并非 df2 中的所有日期都会出现在 df1 中,但它们确实有一个共同的 ID。这是一个例子-

df1 

day           id       key  
1 2020-01-08    A    green
2 2020-01-10    A    green
3 2020-02-24    A    blue 
4 2020-03-24    A    green
   
df2 

day            id   value 
1 2020-01-03    A       2
2 2020-01-07    A       4
3 2020-01-22    A       4
4 2020-03-24    A       6   

desired output

day           id       key    value
1 2020-01-08    A    green        4   
2 2020-01-10    A    green        4
3 2020-02-24    A    blue         4
4 2020-03-24    A    green        6 

【问题讨论】:

  • 在使用sample或其他随机函数时需要先set.seed()才能使结果重现。
  • 如果您也对 data.table 替代方案感兴趣,这是一个“滚动连接” - setDT(df2)[setDT(df1), on=.(key,day), roll=+Inf],您就完成了。
  • 考虑到问题的更新,数据表解决方案会起作用吗?
  • 您可以检查所需输出中的最后两个值吗?我认为他们应该是 6 和 6。
  • 感谢您的帮助,罗纳克。我相信他们应该是 4 和 6

标签: r tidyverse


【解决方案1】:

合并后,您可以arrange基于keydayfill的数据与最近的非NA值。

library(dplyr)

merge(df1, df2, by = c('day', 'key'), all.x = TRUE) %>%
  arrange(key, day) %>%
  group_by(key) %>%
  tidyr::fill(value_y) %>%
  arrange(day)

#          day   key value_x value_y
#1  2020-01-01 green      40       2
#2  2020-01-02  blue      45      NA
#3  2020-01-03 green      54       2
#4  2020-01-04  blue      11       4
#5  2020-01-05 green      12       2
#6  2020-01-06  blue       7       4
#7  2020-01-07 green      72       6
#8  2020-01-08  blue      76       4
#9  2020-01-09 green      52       6
#10 2020-01-10  blue      32       8
#11 2020-01-11 green      69       6
#12 2020-01-12  blue      10       8
#13 2020-01-13 green      63       6
#14 2020-01-14  blue      84       8

对于更新的数据,您可以使用以下内容:

df1 %>%
  left_join(df2, by = 'id') %>%
  mutate(diff = day.x - day.y) %>%
  group_by(id, key, day.x) %>%
  filter(diff == min(diff[diff >= 0])) %>%
  arrange(day.x) %>%
  select(day = day.x, id, key, value)

#   day        id    key   value
#  <date>     <chr> <chr> <int>
#1 2020-01-08 A     green     4
#2 2020-01-10 A     green     4
#3 2020-02-24 A     blue      4
#4 2020-03-24 A     green     6

【讨论】:

  • 我可以按键分组吗?我想知道我是否有更多的键值和更多的日期,所以最近的非 na 值可能属于不同的键
  • 是的,我认为最好按key 分组。更新了答案。
  • 这并没有解决我的用例。我将更新描述以反映原因。问题是这假设 df2 中的日期都出现在 df1
  • @Cauder 更新了答案。
  • 我不确定这是否会中断,但data.table 通常更快。
猜你喜欢
  • 2018-04-26
  • 2022-01-06
  • 2020-11-01
  • 2020-11-21
  • 1970-01-01
  • 2015-03-26
  • 2018-02-25
  • 1970-01-01
相关资源
最近更新 更多