【问题标题】:Fuzzy join - match one sided模糊连接 - 匹配一侧
【发布时间】:2020-03-22 07:56:08
【问题描述】:

我正在尝试从一个表 (myChickWts) 中收集体重值,这些值是在另一个表 (chickblood) 中记录每个血液样本之前一周收集的。我想获取每个血样前一周的血日期和相关重量的列表。我尝试了几种不同的方法,但我不断得到日期在我的结果中包含的血样日期之后。

在此示例中,匹配返回的日期都在血腥日期之前(1/9、1/11、1/13)和之后(1/15)。我怎样才能匹配这两个表?我也尝试过 difference_join,但它在我的另一个结果之前 7 天和之后 7 天返回了结果 - 再次,不是我想要的。

Chick   Date.x (blood)  Date.y (weight)  Chick.y  Weight.y
10     2019-01-14       2019-01-09       10       74
10     2019-01-14       2019-01-11       10       81
10     2019-01-14       2019-01-13       10       89
10     2019-01-14       2019-01-15       10       96




library(tidyverse)
library(lubridate)
library(fuzzyjoin)

导入数据(reprex 的样本数据)

mychickwts <- datasets::ChickWeight %>%
  mutate(Date = date("2019-01-01") + Time) %>%
  select(Date, Chick, weight) %>%
  filter(Chick <= 10)

chickblood <- data.frame(
       Chick = c(1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7,
                 8, 8, 8, 9, 9, 9, 10, 10, 10),
        Date = date(c("2019-01-01", "2019-01-12", "2019-01-22", "2019-01-06",
                 "2019-01-15", "2019-01-22", "2019-01-05", "2019-01-07",
                 "2019-01-14", "2019-01-03", "2019-01-08", "2019-01-11", "2019-01-02",
                 "2019-01-20", "2019-01-23", "2019-01-12", "2019-01-16",
                 "2019-01-18", "2019-01-10", "2019-01-10", "2019-01-22", "2019-01-03",
                 "2019-01-04", "2019-01-08", "2019-01-06", "2019-01-14",
                 "2019-01-17", "2019-01-02", "2019-01-14", "2019-01-21")))

确定体重日期是否在验血日期的前一周。

compare <- function(a, b) {
  (a - b) <= 7
}

获取过去 7 天内每个血样日期和所有匹配体重的表格。这不起作用。

chickblood %>%
fuzzy_left_join(
  mychickwts,
  by = c(
    "Chick" = "Chick",
    "Date" = "Date"
    ),
  match_fun = list(`==`, `compare`)
  )

我也尝试过使用 difference_join,但在这种情况下,我似乎无法弄清楚如何让它与小鸡匹配,并且它会在日期之前和之后返回。

   chickblood %>%
    difference_join(mychickwts, by = "Date",
       max_dist = 7
      )

我尝试使用 lubridate 中的 %within% ,但没有成功。这会返回一个错误,我不确定究竟是什么原因。

chickblood %>%
fuzzy_left_join(
  mychickwts,
  by = c("Chick" = "Chick", 
         "Date" = "Date"),
  match_fun = list("==", "%within%")
  ) %>%
  arrange(Date.x)

Error in which(m) : argument to 'which' is not logical

【问题讨论】:

    标签: r date tidyverse fuzzyjoin


    【解决方案1】:

    由于数据集不是太大,您可以对“Chick”进行正常的左连接,然后确定体重日期是否在验血日期的前一周。从那里你可以保留你想要的行。

    library(tidyverse)
    library(lubridate)
    library(fuzzyjoin)
    
    mychickwts$Chick <- as.numeric(mychickwts$Chick)
    
    chickblood %>% 
      left_join(mychickwts, by = "Chick", suffix = c(".blood", ".wt")) %>% 
      mutate(wt_days_prior = Date.blood - Date.wt) %>% 
      mutate(wt_in_week_prior = wt_days_prior <= 7 & wt_days_prior >= 0) %>% 
      filter(wt_in_week_prior)
    

    或者,如果您想在单个联接中执行此操作,这样的方法可能会起作用。

    chickblood %>% 
      fuzzy_left_join(mychickwts, by = c("Chick", "Date"),
                      match_fun = list(`==`, function(x, y) x - y >= 0 & x - y <= 7)
      )
    

    将fuzzy_left_join 替换为fuzzy_inner_join 以仅保留体重日期在前一周的血液测量值。

    【讨论】:

    • 好吧,我的真实数据集有大约 800 万条记录,但你的两种方法都有效!在沿着一条或另一条路径前进之前,我将对我的数据进行子集化并进行一些速度测试。谢谢!
    猜你喜欢
    • 2020-01-14
    • 1970-01-01
    • 2021-02-06
    • 1970-01-01
    • 1970-01-01
    • 2016-02-11
    • 2021-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多