【问题标题】:replace zero value of one dataset by last values of second dataset in R by key将一个数据集的零值替换为 R 中第二个数据集的最后一个值
【发布时间】:2019-08-29 10:22:49
【问题描述】:

我的数据

  mydata=structure(list(ID_WORKES = c(1000561L, 1000561L, 1000561L, 1000561L, 
    1000561L, 1000561L, 1000562L, 1000562L, 1000562L, 1000562L, 1000562L, 
    1000562L), ID_SP_0R = c(21L, 463L, 465L, 500L, 600L, 1951L, 21L, 
    463L, 465L, 500L, 600L, 1951L), KOD_DEPO = c(0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L), KOD_DOR = c(0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L), COLUMN_MASH = c(0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L), prop_violations = c(0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), mash_score = c(0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L)), .Names = c("ID_WORKES", 
    "ID_SP_0R", "KOD_DEPO", "KOD_DOR", "COLUMN_MASH", "prop_violations", 
    "mash_score"), class = "data.frame", row.names = c(NA, -12L))

第二个数据有这样的格式

mydata2=structure(list(ID_SP_NAR = c(146L, 1088L, 1612L, 30L, 745L, 905L
), KOD_DEPO = c(4575L, 8998L, 8134L, 4038L, 9540L, 683L), KOD_DOR = c(94L, 
94L, 76L, 76L, 94L, 94L), ID_MASH = c(1000561L, 1000561L, 1000561L, 
1000561L, 1000562L, 1000562L), COLUMN_MASH = c(10L, 2L, 1L, 1L, 
17L, 5L), n_routes_total = c(15L, 14L, 25L, 11L, 18L, 4L), n_violations = c(15L, 
10L, 13L, 8L, 7L, 4L), is_violation = c(1L, 1L, 1L, 1L, 1L, 1L
), prop_violations = structure(c(3L, 4L, 1L, 5L, 2L, 6L), .Label = c("0.04000000", 
"0.05555556", "0.06666667", "0.07142857", "0.09090909", "0.25000000"
), class = "factor")), .Names = c("ID_SP_NAR", "KOD_DEPO", "KOD_DOR", 
"ID_MASH", "COLUMN_MASH", "n_routes_total", "n_violations", "is_violation", 
"prop_violations"), class = "data.frame", row.names = c(NA, -6L
))

变量KOD_DEPO, KOD_DOR, COLUMN_MASH 的值如何为零 从 mydata 数据集中替换为每个 ID_WORKES 的 mydata2 数据集中这些变量的最后一个值 ID_WORKER=ID_MASH 是加入的关键变量。

所以想要的输出。 对于id_mash =1000561,mydata2 中的最后一个 kod_depo 是 4038,kod_dor 是 76,COLUMN_MASH 是 1 对于id_mash =1000562,mydata2 中的最后一个 depo 是 683,kod_dor 是 94,并且 COLUMN_MASH 是 5

   ID_WORKES ID_SP_0R KOD_DEPO KOD_DOR COLUMN_MASH prop_violations mash_score
1    1000561       21     4038      76           1               0          0
2    1000561      463     4038      76           1               0          0
3    1000561      465     4038      76           1               0          0
4    1000561      500     4038      76           1               0          0
5    1000561      600     4038      76           1               0          0
6    1000561     1951     4038      76           1               0          0
7    1000562       21      683      94           5               0          0
8    1000562      463      683      94           5               0          0
9    1000562      465      683      94           5               0          0
10   1000562      500      683      94           5               0          0
11   1000562      600      683      94           5               0          0
12   1000562     1951        1       1           1               0          0

怎么做,简单的合并是行不通的。 prop_violations 和 mash_score 不能替代。

【问题讨论】:

    标签: r dplyr data.table tidyr


    【解决方案1】:

    这是使用基数 R 的一种方式。我们将 split mydatamydata2 基于 ID,这样我们在 Map 中就有相同的 ID 调用。 replace cols 对应列中的最后一个值的全部为 0 mydata2

    cols <- c("KOD_DEPO", "KOD_DOR","COLUMN_MASH")
    
    mydata[cols] <- do.call(rbind, Map(function(x, y) 
              sapply(cols, function(p) replace(x[[p]], x[[p]] == 0, tail(y[[p]], 1))),
              split(mydata[c("ID_WORKES",cols)], mydata$ID_WORKES), 
              split(mydata2[c("ID_MASH",cols)], mydata2$ID_MASH)))
    
    
    mydata
    
    #   ID_WORKES ID_SP_0R KOD_DEPO KOD_DOR COLUMN_MASH prop_violations mash_score
    #1    1000561       21     4038      76           1               0          0
    #2    1000561      463     4038      76           1               0          0
    #3    1000561      465     4038      76           1               0          0
    #4    1000561      500     4038      76           1               0          0
    #5    1000561      600     4038      76           1               0          0
    #6    1000561     1951     4038      76           1               0          0
    #7    1000562       21      683      94           5               0          0
    #8    1000562      463      683      94           5               0          0
    #9    1000562      465      683      94           5               0          0
    #10   1000562      500      683      94           5               0          0
    #11   1000562      600      683      94           5               0          0
    #12   1000562     1951        1       1           1               0          0
    

    【讨论】:

    • 黑魔法。但它确实假设ID_WORKES/ID_MASH 以相同的顺序出现并且没有遗漏,不是吗?
    • @MrGumble 是的,确实如此。但是,我认为首先order 他们并不难,以便他们在需要时遵循相同的顺序。
    【解决方案2】:

    首先,您需要将mydata2 单独减少到“最后一个”条目。请注意,除了初始顺序之外,您的数据不会显示任何可供订购的内容。

    library(dplyr)
    (last_mash <- mydata2 %>% group_by(ID_MASH) %>%
      mutate(row=1:n()) %>% top_n(1, row))
    # A tibble: 2 x 10
    # Groups:   ID_MASH [2]
      ID_SP_NAR KOD_DEPO KOD_DOR ID_MASH COLUMN_MASH n_routes_total n_violations is_violation prop_violations   row
          <int>    <int>   <int>   <int>       <int>          <int>        <int>        <int> <fct>           <int>
    1        30     4038      76 1000561           1             11            8            1 0.09090909          4
    2       905      683      94 1000562           5              4            4            1 0.25000000          2
    

    接下来,我们使用它与mydata 合并,但我将使用inner_join

    inner_join(mydata, last_mash, by=c('ID_WORKES'='ID_MASH'), suffix=c('','.y'))
       ID_WORKES ID_SP_0R KOD_DEPO KOD_DOR COLUMN_MASH prop_violations mash_score ID_SP_NAR KOD_DEPO.y KOD_DOR.y
    1    1000561       21        0       0           0               0          0        30       4038        76
    2    1000561      463        0       0           0               0          0        30       4038        76
    3    1000561      465        0       0           0               0          0        30       4038        76
    4    1000561      500        0       0           0               0          0        30       4038        76
    5    1000561      600        0       0           0               0          0        30       4038        76
    6    1000561     1951        0       0           0               0          0        30       4038        76
    7    1000562       21        0       0           0               0          0       905        683        94
    8    1000562      463        0       0           0               0          0       905        683        94
    9    1000562      465        0       0           0               0          0       905        683        94
    10   1000562      500        0       0           0               0          0       905        683        94
    11   1000562      600        0       0           0               0          0       905        683        94
    12   1000562     1951        1       1           1               0          0       905        683        94
       COLUMN_MASH.y n_routes_total n_violations is_violation prop_violations.y row
    1              1             11            8            1        0.09090909   4
    2              1             11            8            1        0.09090909   4
    3              1             11            8            1        0.09090909   4
    4              1             11            8            1        0.09090909   4
    5              1             11            8            1        0.09090909   4
    6              1             11            8            1        0.09090909   4
    7              5              4            4            1        0.25000000   2
    8              5              4            4            1        0.25000000   2
    9              5              4            4            1        0.25000000   2
    10             5              4            4            1        0.25000000   2
    11             5              4            4            1        0.25000000   2
    12             5              4            4            1        0.25000000   2
    

    您会注意到有几列出现了两次,一列没有后缀,另一列带有.y 后缀。试着弄清楚是什么。

    从这里开始,更新零值就像在公园里散步:

    inner_join(mydata, last_mash, by=c('ID_WORKES'='ID_MASH'), suffix =c('','.y')) %>%
      mutate(
        KOD_DEPO=ifelse(KOD_DEPO==0, KOD_DEPO.y, KOD_DEPO),
        KOD_DOR=ifelse(KOD_DOR==0, KOD_DOR.y, KOD_DOR),
        COLUMN_MASH=ifelse(COLUMN_MASH==0, COLUMN_MASH.y, COLUMN_MASH)
      ) %>% select(-ends_with('.y'), -row)
    

    【讨论】:

    • 注意到 Ronak 的方法,将 inner_join 替换为 left_join 以避免删除 ID_WORKESmydata2 中缺少对应项的情况。
    【解决方案3】:

    这是data.table的选项:

    # Setup 
    library(data.table)
    setDT(mydata)
    setDT(mydata2)
    vars2update <- c("KOD_DEPO", "KOD_DOR", "COLUMN_MASH")
    rows2update <- mydata[, rowSums(.SD == 0L) == 3L, .SDcols = vars2update]
    
    # Join and update variables
    mydata[rows2update, 
           (vars2update) := mydata2[.SD, 
                                    on = .(ID_MASH = ID_WORKES), 
                                    mult = "last", 
                                    mget(vars2update)]]
    
    #     ID_WORKES ID_SP_0R KOD_DEPO KOD_DOR COLUMN_MASH prop_violations mash_score
    #  1:   1000561       21     4038      76           1               0          0
    #  2:   1000561      463     4038      76           1               0          0
    #  3:   1000561      465     4038      76           1               0          0
    #  4:   1000561      500     4038      76           1               0          0
    #  5:   1000561      600     4038      76           1               0          0
    #  6:   1000561     1951     4038      76           1               0          0
    #  7:   1000562       21      683      94           5               0          0
    #  8:   1000562      463      683      94           5               0          0
    #  9:   1000562      465      683      94           5               0          0
    # 10:   1000562      500      683      94           5               0          0
    # 11:   1000562      600      683      94           5               0          0
    # 12:   1000562     1951        1       1           1               0          0
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-18
      • 1970-01-01
      • 1970-01-01
      • 2020-04-11
      • 2015-12-14
      • 1970-01-01
      相关资源
      最近更新 更多