如何找到一列中的值与多列中的值的最小差异

how to find the min difference from a value in one col to the value from multiple cols

我有一个如下所示的 df。我想找到在 date 之前发生的最近日期 (from R_1:R_10)。是不是可以一次计算R1:R10date的天数差,然后挑出我们想要的值,然后把它放在一个新的变量cdate中?

输出将如下所示:

cdate 将由 R_1:R10-date 标识,负值最大的那个将是我们输入 cdate

的日期

示例数据:

df<-structure(list(id = c("A0003", "A0003", "A0003", "A0003", "A0003", 
"A0003", "A0005", "A0005"), date = structure(c(17774, 17799, 
17805, 17837, 17846, 17873, 17784, 17784), class = "Date"), R_1 = structure(c(17773, 
17773, 17773, 17773, 17773, 17773, 17785, 17785), class = "Date"), 
    R_2 = structure(c(17815, 17815, 17815, 17815, 17815, 17815, 
    17827, 17827), class = "Date"), R_5 = structure(c(17794, 
    17794, 17794, 17794, 17794, 17794, 17806, 17806), class = "Date"), 
    R_10 = structure(c(17871, 17871, 17871, 17871, 17871, 17871, 
    NA, NA), class = "Date")), row.names = c(NA, 8L), class = "data.frame")

我们可以将数据加入汇总版本,通过将数据旋转更长的时间,按 id 和日期分组,过滤掉 R_x 较晚的日期,并对最后一个进行汇总。

library(dplyr)
df %>%
  left_join(
    df %>%
      tidyr::pivot_longer(-c(id,date)) %>%
      group_by(id, date) %>%
      filter(value <= date) %>%
      summarize(cdate = max(value), .groups = "drop")
  )

结果

Joining, by = c("id", "date")
     id       date        R_1        R_2        R_5       R_10      cdate
1 A0003 2018-08-31 2018-08-30 2018-10-11 2018-09-20 2018-12-06 2018-08-30
2 A0003 2018-09-25 2018-08-30 2018-10-11 2018-09-20 2018-12-06 2018-09-20
3 A0003 2018-10-01 2018-08-30 2018-10-11 2018-09-20 2018-12-06 2018-09-20
4 A0003 2018-11-02 2018-08-30 2018-10-11 2018-09-20 2018-12-06 2018-10-11
5 A0003 2018-11-11 2018-08-30 2018-10-11 2018-09-20 2018-12-06 2018-10-11
6 A0003 2018-12-08 2018-08-30 2018-10-11 2018-09-20 2018-12-06 2018-12-06
7 A0005 2018-09-10 2018-09-11 2018-10-23 2018-10-02       <NA>       <NA>
8 A0005 2018-09-10 2018-09-11 2018-10-23 2018-10-02       <NA>       <NA>

使用base R,我们用lapplyreplace遍历'R_'列大于'date'到[=15=的值],然后使用 pmax 到 return max 日期值

df$cdate <-  do.call(pmax, c(lapply(df[grep("R_", names(df))], 
     \(x) replace(x, x > df$date, NA)), na.rm = TRUE))

-输出

> df
     id       date        R_1        R_2        R_5       R_10      cdate
1 A0003 2018-08-31 2018-08-30 2018-10-11 2018-09-20 2018-12-06 2018-08-30
2 A0003 2018-09-25 2018-08-30 2018-10-11 2018-09-20 2018-12-06 2018-09-20
3 A0003 2018-10-01 2018-08-30 2018-10-11 2018-09-20 2018-12-06 2018-09-20
4 A0003 2018-11-02 2018-08-30 2018-10-11 2018-09-20 2018-12-06 2018-10-11
5 A0003 2018-11-11 2018-08-30 2018-10-11 2018-09-20 2018-12-06 2018-10-11
6 A0003 2018-12-08 2018-08-30 2018-10-11 2018-09-20 2018-12-06 2018-12-06
7 A0005 2018-09-10 2018-09-11 2018-10-23 2018-10-02       <NA>       <NA>
8 A0005 2018-09-10 2018-09-11 2018-10-23 2018-10-02       <NA>       <NA>