代码之家  ›  专栏  ›  技术社区  ›  Denis

如何查找查找数据中最近的行。基于多个列的框架?

  •  0
  • Denis  · 技术社区  · 5 年前

    v <- data.frame(d = c(as.Date('2019-01-01'), as.Date('2019-01-05'), as.Date('2019-01-30'), as.Date('2019-02-02')), kind=c('a', 'b', 'c', 'a'), v1=c(1,2,3,4))
    v
               d kind v1
    1 2019-01-01    a  1
    2 2019-01-05    b  2
    3 2019-01-30    c  3
    4 2019-02-02    a  4
    
    l <- data.frame(d = c(as.Date('2019-01-01'), as.Date('2019-01-04'), as.Date('2019-02-01')), kind=c('a','b','a'), l1=c(10,20,30))
    l
               d kind l1
    1 2019-01-01    a 10
    2 2019-01-04    b 20
    3 2019-02-01    a 30
    

    我想在列表中找到最近的一行 l 使用列与v中的每一行对应的数据帧: c("d", "kind") kind 需要精确匹配,可能需要使用 findInterval(...) d ?

               d kind v1 l1
    1 2019-01-01    a  1 10
    2 2019-01-05    b  2 20
    3 2019-01-30    c  3 NA
    4 2019-02-02    a  4 30
    

    注意:我更喜欢base-R实现,但它是 见到别人很有趣

    findInterval(…)

    0 回复  |  直到 5 年前
        1
  •  2
  •   r2evans    5 年前

    这里有一个只在R垒的镜头。(我相信 data.table 这样做会更加优雅,但我很感激你不愿意带其他包裹。)

    按将每个帧拆分为帧列表 kind

    v_spl <- split(v, v$kind)
    l_spl <- split(l, l$kind)
    str(v_spl)
    # List of 3
    #  $ a:'data.frame':    2 obs. of  3 variables:
    #   ..$ d   : Date[1:2], format: "2019-01-01" "2019-02-02"
    #   ..$ kind: Factor w/ 3 levels "a","b","c": 1 1
    #   ..$ v1  : num [1:2] 1 4
    #  $ b:'data.frame':    1 obs. of  3 variables:
    #   ..$ d   : Date[1:1], format: "2019-01-05"
    #   ..$ kind: Factor w/ 3 levels "a","b","c": 2
    #   ..$ v1  : num 2
    #  $ c:'data.frame':    1 obs. of  3 variables:
    #   ..$ d   : Date[1:1], format: "2019-01-30"
    #   ..$ kind: Factor w/ 3 levels "a","b","c": 3
    #   ..$ v1  : num 3
    

    友善的 我们两者之间有共同点,不需要尝试加入所有内容:

    ### this has the 'kind' in common
    (nms <- intersect(names(v_spl), names(l_spl)))
    # [1] "a" "b"
    
    ### this has the 'kind' we have to bring back in later
    (miss_nms <- setdiff(names(v_spl), nms))
    # [1] "c"
    

    为了共同利益 ,执行间隔联接:

    joined <- Map(
      v_spl[nms], l_spl[nms],
      f = function(v0, l0) {
        ind <- findInterval(v0$d, l0$d)
        ind[ ind < 1 ] <- NA
        v0$l1 <- l0$l1[ind]
        v0
      })
    

    最终我们会的 rbind 一切都恢复了,但那些 miss_nms 将不会有新列。这是一种通用的方法,可以使用适当的 NA 价值:

    emptycols <- joined[[1]][, setdiff(colnames(joined[[1]]), colnames(v)),drop=FALSE][1,,drop=FALSE][NA,,drop=FALSE]
    emptycols
    #    l1
    # NA NA
    

    并将该列添加到尚未找到的帧中:

    unjoined <- lapply(v_spl[miss_nms], cbind, emptycols)
    unjoined
    # $c
    #            d kind v1 l1
    # 3 2019-01-30    c  3 NA
    

    最后,将所有内容放回一个框架中:

    do.call(rbind, c(joined, unjoined))
    #              d kind v1 l1
    # a.1 2019-01-01    a  1 10
    # a.4 2019-02-02    a  4 30
    # b   2019-01-05    b  2 20
    # c   2019-01-30    c  3 NA
    
        2
  •  0
  •   Orlando Sabogal    5 年前

     vl <- merge(v, l, by = c("d","kind"))
    

    合并