我有以下data.table:

dt
#    unique_id group_id primary_id  ph1  ph2  ph3
# 1:         1        1       TRUE   07   03 <NA>
# 2:         2        1      FALSE   07   03   84
# 3:         3        2      FALSE   10 <NA> <NA>
# 4:         4        2       TRUE <NA>   10 <NA>
# 5:         5        2      FALSE <NA> <NA>   10
# 6:         6        3      FALSE   22   03 <NA>
# 7:         7        3       TRUE <NA>   13   03
unique_ids按行之间通用的公用电话号码(ph1ph2ph3)分组(例如,第一组“07”,“03”在整个组中是公用的,而在第三组中,“03”是共享的,但不在同一列中(按照第2组)。

每组有1个primary_id

在每个组中,我想删除非primary_id中的公用电话号码元素,并将其保留为主要ID,以便不再链接它们。

我可以在for循环中轻松实现这一点,但是,它遍历了数百万个小组,而且非常慢。

寻找更快的方法。

数据:
library(data.table)

dt <- data.table(structure(list(unique_id = c(1, 2, 3, 4, 5, 6, 7), group_id = c(1,
    1, 2, 2, 2, 3, 3), primary_id = c(TRUE, FALSE, FALSE, TRUE, FALSE,
    FALSE, TRUE), ph1 = c("07", "07", "10", NA, NA, "22", NA), ph2 = c("03",
    "03", NA, "10", NA, "03", "13"), ph3 = c(NA, "84", NA, NA, "10",
    NA, "03")), class = "data.frame", row.names = c(NA, -7L))
)

所需的输出是:
output <- data.table(structure(list(unique_id = c(1, 2, 3, 4, 5, 6, 7), group_id = c(1,
1, 2, 2, 2, 3, 3), primary_id = c(TRUE, FALSE, FALSE, TRUE, FALSE,
FALSE, TRUE), ph1 = c("07", NA, NA, NA, NA, "22", NA), ph2 = c("03",
NA, NA, "10", NA, NA, "13"), ph3 = c(NA, "84", NA, NA, NA, NA,
"03")), class = "data.frame", row.names = c(NA, -7L)))

output
#    unique_id group_id primary_id  ph1  ph2  ph3
# 1:         1        1       TRUE   07   03 <NA>
# 2:         2        1      FALSE <NA> <NA>   84
# 3:         3        2      FALSE <NA> <NA> <NA>
# 4:         4        2       TRUE <NA>   10 <NA>
# 5:         5        2      FALSE <NA> <NA> <NA>
# 6:         6        3      FALSE   22 <NA> <NA>
# 7:         7        3       TRUE <NA>   13   03

如果仍然不清楚,则可以更容易地将其可视化,如下所示:

r - 有效地从分组数据中删除共享元素-LMLPHP

最佳答案

使用data.table语法,以下内容将重现您的预期输出

dcast(
    setorder(
        melt(dt, id.vars = 1:3, measure.vars = 4:6),
        group_id, -primary_id)[
            which(duplicated(value)), value := NA, by = "group_id"],
    unique_id + group_id + primary_id ~ variable, value.var = "value")
#   unique_id group_id primary_id  ph1  ph2  ph3
#1:         1        1       TRUE   07   03 <NA>
#2:         2        1      FALSE <NA> <NA>   84
#3:         3        2      FALSE <NA> <NA> <NA>
#4:         4        2       TRUE <NA>   10 <NA>
#5:         5        2      FALSE <NA> <NA> <NA>
#6:         6        3      FALSE   22 <NA> <NA>
#7:         7        3       TRUE <NA>   13 <NA>

说明:想法是将数据从宽到长整形,并按group_idprimary_id排序条目(以primary_id == TRUE首先出现);然后我们使用duplicated(通过group_id)标记重复的行,并将重复的条目设置为NA,然后再次从宽变长。

10-04 21:52
查看更多