【问题标题】:Merge data frame based on vector key基于向量键合并数据框
【发布时间】:2013-10-01 14:35:46
【问题描述】:

我是一个绝对的初学者,我希望有人能够帮助我解决我今晚大部分时间都坚持的合并问题,并且迄今为止无法成功地将解决方案适应类似问题具体例子。

我制作了一个虚拟数据框和向量来帮助说明我的问题:

dumdata <- data.frame(id=c(1:5), pcode=c(1234,9876,4477,2734,3999), vlo=c(100,450,1000,1325,1500), vhi=c(300,950,1100,1450,1700))

id pcode  vlo  vhi
 1  1234  100  300
 2  9876  450  950
 3  4477 1000 1100
 4  2734 1325 1450
 5  3999 1500 1700


vkey <- c(105,290,513,1399,1572,1683)

在 vkey 的值介于变量 vlo 和 vhi 之间的情况下,我想输出一个包含 dumdata 数据的新数据帧。在实际应用中,vkey 的值总是在一个 vlo-vhi 范围之间,而且范围总是离散的。

所需的输出如下所示:

id   pcode   vlo   vhi  vkey
 1    1234   100   300   105
 1    1234   100   300   290
 2    9876   450   950   513
 4    2734  1325  1450  1399
 5    3999  1500  1700  1572
 5    3999  1500  1700  1683

【问题讨论】:

    标签: r merge dataframe


    【解决方案1】:

    您可以使用sapply 一次性构建整个索引向量,而不是使用for 循环。

    ind <- sapply(vkey, function(x) which(dumdata$vlo < x & x < dumdata$vhi))
    data.frame(dumdata[ind,], vkey)
    
        id pcode  vlo  vhi vkey
    1    1  1234  100  300  105
    1.1  1  1234  100  300  290
    2    2  9876  450  950  513
    4    4  2734 1325 1450 1399
    5    5  3999 1500 1700 1572
    5.1  5  3999 1500 1700 1683
    

    如果vkey 中的任何值与dumdata 中的多行匹配,它会变得更丑陋,因为您需要使用lapply 而不是 sapply 然后这样做

    data.frame(dumdata[unlist(ind),], rep(vkey, sapply(vkey, length)))
    

    返回所有匹配项,但我从示例中得出它不会发生。

    编辑:

    为了完整起见,我要补充一点,您也可以使用 mapply,但这主要用于需要与多个变量进行比较的情况(例如,如果您有 vkey1vkey2需要一起满足一个条件)。

    ind <- mapply(function(x, y) which(dumdata$vlo < x & y < dumdata$vhi),
                  vkey1, vkey2)
    

    【讨论】:

    • 由于只有一个参数,因此使用sapply 也可以,但很难与成功争论。
    • 当然!我有点草率选择了mapply,因为vlovhi有两个>_
    • 我会将mapply 版本放在底部作为替代方案。它的优点是可以推广到多参数设置。 (它也有不同的语法。)
    【解决方案2】:

    使用 data.table 包。

    library(data.table)
    
    # added a blank vkeyvalue column
    dumdata <- data.table(
       id=c(1:5), 
       pcode=c(1234,9876,4477,2734,3999), 
       vlo=c(100,450,1000,1325,1500), 
       vhi=c(300,950,1100,1450,1700),
       vkeyvalue = as.integer(NA)
    )
    
    #initialising the final dataset being populated with the same structure as dumdata
    finalfiltereddata <- dumdata[0]
    vkey <- c(105,290,513,1399,1572,1683)
    
    # looping throug each key
    for ( i in vkey)
    {
    #subsetting dumdata for values which meet the condition vlo < i & vhi > i
    filtereddata <- dumdata[vlo < i & vhi > i]
    
    #assigning the filtered data the respective vkeyvalue
    filtereddata[, vkeyvalue := as.integer(i)]
    
    #appending to the master data set
    finalfiltereddata <- rbind(finalfiltereddata, filtereddata)
    }
    
    finalfiltereddata
    
       # id pcode  vlo  vhi vkeyvalue
    # 1:  1  1234  100  300       105
    # 2:  1  1234  100  300       290
    # 3:  2  9876  450  950       513
    # 4:  4  2734 1325 1450      1399
    # 5:  5  3999 1500 1700      1572
    # 6:  5  3999 1500 1700      1683
    

    【讨论】:

      【解决方案3】:

      一种选择可能是使用cut 为您的“vkey”变量创建一个匹配的“id”列,如下所示:

      cutBreaks <- sort(unlist(dumdata[c("vlo", "vhi")], use.names = FALSE))
      cutLabels <- rep(1:nrow(dumdata), each = 2) * c(1, -1)
      
      new <- data.frame(vals = vkey, id = cut(vkey, breaks = cutBreaks, 
                                              labels = cutLabels[-length(cutLabels)]))
      new
      #   vkey id
      # 1  105  1
      # 2  290  1
      # 3  513  2
      # 4 1399  4
      # 5 1572  5
      # 6 1683  5
      

      一旦你有了它,merge 应该可以毫无问题地工作:

      merge(new, dumdata)
      #   id vkey pcode  vlo  vhi
      # 1  1  105  1234  100  300
      # 2  1  290  1234  100  300
      # 3  2  513  9876  450  950
      # 4  4 1399  2734 1325 1450
      # 5  5 1572  3999 1500 1700
      # 6  5 1683  3999 1500 1700
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-07-20
        • 2011-10-12
        • 2018-01-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-17
        相关资源
        最近更新 更多