【问题标题】:r Replace only some table values with values from alternate tabler 仅用备用表中的值替换某些表值
【发布时间】:2019-03-03 06:47:54
【问题描述】:

这不是“vlookup-and-fill-down”问题。

我的源数据非常擅长提供我需要的所有数据,只是没有以可用的形式。最近音量的变化意味着手动调整的修复不再可行。

我有一个库存表和一个服务表。库存报告不包含服务或非库存项目的采购订单数据。服务表(自然)确实如此。它们当然是不同的形状。

伪编码会产生for every inventory$Item in services$Item, replace inventory$onPO with services$onPO 的效果。

样本数据

inv <- structure(list(Item = c("10100200", "10100201", "10100202", "10100203", 
"10100204", "10100205-A", "10100206", "10100207", "10100208", 
"10100209", "10100210"), onHand = c(600L, NA, 39L, 0L, NA, NA, 
40L, 0L, 0L, 0L, 0L), demand = c(3300L, NA, 40L, 40L, NA, NA, 
70L, 126L, 10L, 10L, 250L), onPO = c(2700L, NA, 1L, 40L, NA, 
NA, 30L, 126L, 10L, 10L, 250L)), .Names = c("Item", "onHand", 
"demand", "onPO"), row.names = c(NA, -11L), class = c("data.table", 
"data.frame"))

svc <- structure(list(Item = c("10100201", "10100204", "10100205-A"), 
    `Rcv'd` = c(0L, 0L, 44L), Backordered = c(20L, 100L, 18L)), .Names = c("Item", 
"Rcv'd", "Backordered"), row.names = c(NA, -3L), class = c("data.table", 
"data.frame"))

【问题讨论】:

    标签: r vlookup replacewith


    【解决方案1】:

    假设您想用来自Backordered 的值替换onPO 中的NAs,这是使用dplyr::left_join 的解决方案:

    library(dplyr);
    left_join(inv, svc) %>%
        mutate(onPO = ifelse(is.na(onPO), Backordered, onPO)) %>%
        select(-Backordered, -`Rcv'd`);
    #         Item onHand demand onPO
    #1    10100200    600   3300 2700
    #2    10100201     NA     NA   20
    #3    10100202     39     40    1
    #4    10100203      0     40   40
    #5    10100204     NA     NA  100
    #6  10100205-A     NA     NA   18
    #7    10100206     40     70   30
    #8    10100207      0    126  126
    #9    10100208      0     10   10
    #10   10100209      0     10   10
    #11   10100210      0    250  250
    

    或者使用merge在base R中的解决方案:

    inv$onPO <- with(merge(inv, svc, all.x = TRUE), ifelse(is.na(onPO), Backordered, onPO))
    

    或者使用coalesce 代替ifelse(感谢@thelatemail):

    library(dplyr);
    left_join(inv, svc) %>%
        mutate(onPO = coalesce(onPO, Backordered)) %>%
        select(-Backordered, -`Rcv'd`);
    

    【讨论】:

    • 我认为你也可以使用coalesce 而不是ifelse
    • 感谢 Maurits Evers 和 @thelatemail 提供的多种方法 有趣的是,我无法通过 DuckDuckGo-ing SO 找到答案。我想寻找错误的术语。
    【解决方案2】:

    data.table 世界中,这是一个“更新加入”。加入“项目”,然后使用新集合中的值更新原始集合中的值:

    library(data.table)
    setDT(inv)
    setDT(svc)
    
    inv[svc, on="Item", c("onPO","onHand") := .(i.Backordered, `i.Rcv'd`)]
    
    #inv   original table
    #svc   update table
    #on=   match on specified variable
    # :=   overwrite  onPO    with  Backordered
    #                 onHand  with  Rcv'd
    
    
    #          Item onHand demand onPO
    # 1:   10100200    600   3300 2700
    # 2:   10100201      0     NA   20
    # 3:   10100202     39     40    1
    # 4:   10100203      0     40   40
    # 5:   10100204      0     NA  100
    # 6: 10100205-A     44     NA   18
    # 7:   10100206     40     70   30
    # 8:   10100207      0    126  126
    # 9:   10100208      0     10   10
    #10:   10100209      0     10   10
    #11:   10100210      0    250  250
    

    【讨论】:

    • @rawr - 我是 data.table 的忠实粉丝。我不认为我会让任何人失望:-P
    【解决方案3】:

    从表格开始:

      >inv
              Item OnHand Demand OnPO
     1:   10100200    600   3300 2700
     2:   10100201     NA     NA   NA
     3:   10100202     39     40    1
     4:   10100203      0     40   40
     5:   10100204     NA     NA   NA
     6: 10100205-A     NA     NA   NA
     7:   10100206     40     70   30
     8:   10100207      0    126  126
     9:   10100208      0     10   10
    10:   10100209      0     10   10
    11:   10100210      0    250  250
    
    > svc
             Item Rcv'd Backordered
    1:   10100201     0          20
    2:   10100204     0         100
    3: 10100205-A    44          18
    

    经过比我想承认的更多的诅咒,适用于上述测试数据的简单解决方案以及我的实时数据证明是:

    # Insert OnHand and OnPO data from svc
    for (i in 1:nrow(inv)) {
      if(inv$Item[i] %in% svc$Item) {
        x <- which(svc$Item == inv$Item[i])
        inv$OnPO[i] <- svc$Backordered[x]
        inv$OnHand[i] <- svc$`Rcv'd`[x]
      } 
        else{}
    }
    # cleanup 
    inv[is.na(inv)] <- 0
    

    有没有我忽略的更简单或更明显的方法?

    【讨论】:

      【解决方案4】:

      我们可以使用我的包safejoin 中的eat 和“补丁” 列冲突时从右轴匹配到左轴。

      我们在途中将Backordered 重命名为onPO,这样两列就可以根据需要发生冲突。

      # devtools::install_github("moodymudskipper/safejoin")
      library(safejoin)
      library(dplyr)
      
      eat(inv, svc, onPO = Backordered, .conflict = "patch")
      #          Item onHand demand onPO
      # 1    10100200    600   3300 2700
      # 2    10100201     NA     NA   20
      # 3    10100202     39     40    1
      # 4    10100203      0     40   40
      # 5    10100204     NA     NA  100
      # 6  10100205-A     NA     NA   18
      # 7    10100206     40     70   30
      # 8    10100207      0    126  126
      # 9    10100208      0     10   10
      # 10   10100209      0     10   10
      # 11   10100210      0    250  250
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-07-10
        • 2015-04-24
        • 1970-01-01
        • 1970-01-01
        • 2022-10-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多