【问题标题】:Merging with conditions in R与 R 中的条件合并
【发布时间】:2018-04-06 14:03:52
【问题描述】:
varA=c('2018-01-03', '2018-01-25','2018-01-15','2018-01-06')
varB=c('2018-01-02', '2018-01-05', '2018-01-13', '2018-01-21', '2018-01-26')
varC=c(201801,201802,201804,201809,201815)

df1=as.data.frame(varA)
df2=as.data.frame(cbind(varB,varC))

使用上面的代码获取数据帧:

        varA
1 2018-01-03
2 2018-01-25
3 2018-01-15
4 2018-01-06

        varB   varC
1 2018-01-02 201801
2 2018-01-05 201802
3 2018-01-13 201804
4 2018-01-21 201809
5 2018-01-26 201815

由此我想将 df1 和 df2 合并在一起,但如果 varA 作为日期介于 varB 的两个日期之间,它将从最早的日期开始使用 varC。我认为展示我期望的结果会更容易:

       varA    varB         varC
1 2018-01-03  2018-01-02   201801
2 2018-01-25  2018-01-21   201809
3 2018-01-15  2018-01-13   201804
4 2018-01-06  2018-01-05   201802

希望这很清楚。我不确定如何获得所需的输出。

【问题讨论】:

  • 您有什么尝试吗?你试过了吗?
  • 我不知道从哪里开始,我习惯于直接合并。这就是我想在这里发帖的原因。
  • 第一步是创建一个函数,它关联一个varA 值,正确的varB 值(最早等...)。然后您可以使用for/apply 为 DF1 的每一行使用此功能。然后你可以使用merge
  • @timat 我真的不知道该怎么做,所以如果你能创建一个例子会很棒吗?这个问题只有我数据的一小部分,因为我的实际数据有 5000 行。这些行有 100 多个不同的日期。

标签: r merge conditional


【解决方案1】:

您可以使用data.table 进行左连接:

varA <- c('2018-01-03', '2018-01-25','2018-01-15','2018-01-06')
varB <- c('2018-01-02', '2018-01-05', '2018-01-13', '2018-01-21', '2018-01-26')
varC <- c(201801,201802,201804,201809,201815)

library(lubridate)
dt1 <- data.table(varA = ymd(varA))
dt2 <- data.table(varA = ymd(varB), varB = ymd(varB), varC =  varC)
setkey(dt1, varA)
setkey(dt2, varA)

dt2[dt1,, roll = T]

【讨论】:

    【解决方案2】:

    findInterval in base R 在这里可能会有所帮助。例如,

    将 VarA 和 VarB 强制转换为 Date 对象并使用 findInterval 创建一个新列,其中 df2 中的行(即 VarB 索引)与您为每个 VarA 指定的条件相匹配。

    df1$row_match <- findInterval(as.Date(df1$varA), as.Date(df2$varB))
    

    然后创建新的对应列(df2 中的行)以加入/合并

    df2$row_match <- seq_len(nrow(df2))
    
    df3 <- merge(df1, df2, by = "row_match")
    #> df3
    #  row_match       varA       varB   varC
    #1         1 2018-01-03 2018-01-02 201801
    #2         2 2018-01-06 2018-01-05 201802
    #3         3 2018-01-15 2018-01-13 201804
    #4         4 2018-01-25 2018-01-21 201809
    

    【讨论】:

    • 感谢您,当我在整个数据集上运行此程序时,我收到错误:findInterval 错误(as.Date(df1$VarA), as.Date(df2$VarB)) :' vec' 必须非递减排序且不包含 NA。我尝试对列进行排序,以便日期增加,但仍然出现相同的错误?
    • 日期列中是否有任何 NA?您可能必须强制新对象中的日期列作为检查 NA 的中间步骤。
    • 我刚刚重新访问了这个,我在日期列中没有 NA,不知道为什么这个错误仍然发生
    【解决方案3】:

    你可以试试

    library(tidyverse)
    map(df1$varA, function(x)  df2[between(df2$varB, x, x),]) %>% 
      bind_rows() %>% 
      bind_cols(df1,.)
            varA       varB   varC
    1 2018-01-03 2018-01-02 201801
    2 2018-01-25 2018-01-21 201809
    3 2018-01-15 2018-01-13 201804
    4 2018-01-06 2018-01-05 201802
    

    想法是使用 tidyverse 函数map & between 找到区间,然后添加df1

    【讨论】:

      猜你喜欢
      • 2015-07-11
      • 1970-01-01
      • 2016-08-01
      • 2016-12-15
      • 2021-02-03
      • 1970-01-01
      • 2018-02-04
      • 2021-11-28
      相关资源
      最近更新 更多