通过引用更新 data.table,但在使用优先向量存在重复项时仅填充某些行

Update data.table by reference but populate only certain rows when duplicates are present using a prioritized vector

我不太清楚标题的措辞,但这就是我想做的。我想使用 dt2 中的列来增加数据 table dt1。在 dt1 中,我 updating/merging 所在的列中有重复数据。我的目标是仅在满足条件时才重复填充 dt1 中的新列 由另一个变量指定。让我证明我的意思:

library(data.table)


dt1 <- data.table(common_var = c(rep("a", 3), rep("b", 2)),
                  condition_var = c("update1", rep(c("update2", "update3"), 2)),
                  other_var = 1:5)


dt2 <- data.table(common_var = c("a", "b", "C", "d"),
                  new_var1 = 11:14,
                  new_var2 = 21:24)

# What I want to obtain is the following
dt_goal <- data.table(common_var = dt1$common_var,
                      condition_var = dt1$condition_var,
                      other_var = dt1$other_var,
                      new_var1 = c(11, NA, NA, 12, NA),
                      new_var2 = c(21, NA, NA, 22, NA))
dt_goal

通过引用更新或合并填充所有匹配的行(如预期的那样),但这不是我想要的:

# Updating by reference populates all the duplicate rows as expected
# (doesn't work for my purpose)
dt1[, names(dt2) := as.list(dt2[match(dt1$common_var, dt2$common_var),])]

# merging also populates duplicate rows as expected.
# dt3 <- merge(dt1, dt2, by="common_var")

我尝试用 NA 覆盖合并的 dt3(或更新的 dt1)的行,但我不想有数据:

dt3 <- dt3[which(alldup(dt3$common_var) & dt3$condition_var %in% c("update2", "update3")), names(dt2)[2:3] := NA]
dt3

上述代码中的逻辑发现重复 and 不需要的条件情况,并将所选列替换为 NA。这部分有效,但有两个问题:

1) 如果要保留的值 (update1) 不存在于其他重复行中(在我的示例中为 b),它们也会被删除

2) 这种方法需要 hard-coding 我想保留的案例。在我的 real-world 应用程序中,我将循环这种类型的数据准备,条件值将发生变化。我知道更新数据的优先级 table 不过:

order_to_populate_dups <- c("update1", "update2", "update3")

换句话说,我想要一个代码来增长数据 table 如下:

1)当没有重复时,按引用添加列(或合并)正常

2) 当 id 变量下存在重复时,查看 condition_var

2a) 如果看到update1 添加数据,如果没有,下一步

2b) 如果看到update2 添加数据,如果没有,下一步

2c) 如果看到 update3 添加数据,如果没有,下一步,...

我无法在 SO 中找到此问题的解决方案。如果这是重复的,请告诉我。

谢谢!

如果我理解你的例子是否正确,请告诉我。如果需要,我可以更改解决方案。

# order dt1 by the common variable and 
setorder(dt1, common_var, condition_var) condition
# calculate row_id for each group (grouped by common_var)
dt1[, row_index := rowid(common_var)] 
# assume dt2 has only one row per common_var
dt2[, row_index := 1]

# left join on common_var and row_index, reorder columns.
dt3 <- dt2[dt1, on = c('common_var', 'row_index')][, list(common_var, condition_var, other_var, new_var1, new_var2)]

您是否在寻找类似的东西:

cols <- paste0("new_var", 1:2)
remap <- c(update1=1, update2=2, update3=3)
dt1[, rp := remap[condition_var]]

setkey(dt1, common_var, rp)
dt1[rowid(common_var)==1L, (cols) := 
    dt2[.SD, on=.(common_var), mget(paste0("i.",cols))]

说明: 您可以使用 factor 或向量将字符向量重新映射为可以相应排序的内容。然后使用setkey对数据进行排序,然后对common_var.

的每组第一行执行update join