Это попытка воспроизвести ожидаемый результат в соответствии с правилами ОП.
Я все еще пытаюсь найти решение, используя unique()
, duplicated()
для данных в широком формате, а также для преобразования в длинный формат.
Однако, здесь есть решение, использующее for
l oop, который воспроизводит ожидаемый результат для данного образца набора данных:
library(data.table)
# append row numbers
setDT(DT)[, rn := .I]
# which values appear only once in the `to`` column?
single_to <- DT[, .N, by = to][N == 1L, to]
single_to
[1] 2 1 7
DT[, drop := NA]
for (i in seq_len(nrow(DT))) {
print(i)
print(DT[i])
if (isTRUE(DT$drop[i])) next # row already has been eliminated
act_to <- DT$to[i]
# Rule 1: eliminate subsequent rows with repeated value in `to` column
DT[rn > i & (to == act_to), drop := TRUE]
# Rule 1: eliminate subsequent rows with repeated value in `from` column
# Rule 2: but keep rows where value is unique in the `to` column
DT[rn > i & (from == act_to) & !(to %in% single_to), drop := TRUE]
DT[i, drop := FALSE]
print(DT[])
}
[1] 1
from to distance weight rn drop
1: 1 8 1 10 1 NA
from to distance weight rn drop
1: 1 8 1 10 1 FALSE
2: 2 6 1 9 2 NA
3: 3 4 1 5 3 NA
4: 4 5 3 9 4 NA
5: 5 6 4 8 5 NA
6: 6 2 5 2 6 NA
7: 7 8 2 1 7 TRUE
8: 4 3 5 6 8 NA
9: 2 1 1 7 9 NA
10: 6 8 4 8 10 TRUE
11: 1 7 5 3 11 NA
12: 8 4 6 7 12 TRUE
13: 9 5 3 9 13 NA
14: 10 3 8 2 14 NA
[1] 2
from to distance weight rn drop
1: 2 6 1 9 2 NA
from to distance weight rn drop
1: 1 8 1 10 1 FALSE
2: 2 6 1 9 2 FALSE
3: 3 4 1 5 3 NA
4: 4 5 3 9 4 NA
5: 5 6 4 8 5 TRUE
6: 6 2 5 2 6 NA
7: 7 8 2 1 7 TRUE
8: 4 3 5 6 8 NA
9: 2 1 1 7 9 NA
10: 6 8 4 8 10 TRUE
11: 1 7 5 3 11 NA
12: 8 4 6 7 12 TRUE
13: 9 5 3 9 13 NA
14: 10 3 8 2 14 NA
[1] 3
from to distance weight rn drop
1: 3 4 1 5 3 NA
from to distance weight rn drop
1: 1 8 1 10 1 FALSE
2: 2 6 1 9 2 FALSE
3: 3 4 1 5 3 FALSE
4: 4 5 3 9 4 TRUE
5: 5 6 4 8 5 TRUE
6: 6 2 5 2 6 NA
7: 7 8 2 1 7 TRUE
8: 4 3 5 6 8 TRUE
9: 2 1 1 7 9 NA
10: 6 8 4 8 10 TRUE
11: 1 7 5 3 11 NA
12: 8 4 6 7 12 TRUE
13: 9 5 3 9 13 NA
14: 10 3 8 2 14 NA
[1] 4
from to distance weight rn drop
1: 4 5 3 9 4 TRUE
[1] 5
from to distance weight rn drop
1: 5 6 4 8 5 TRUE
[1] 6
from to distance weight rn drop
1: 6 2 5 2 6 NA
from to distance weight rn drop
1: 1 8 1 10 1 FALSE
2: 2 6 1 9 2 FALSE
3: 3 4 1 5 3 FALSE
4: 4 5 3 9 4 TRUE
5: 5 6 4 8 5 TRUE
6: 6 2 5 2 6 FALSE
7: 7 8 2 1 7 TRUE
8: 4 3 5 6 8 TRUE
9: 2 1 1 7 9 NA
10: 6 8 4 8 10 TRUE
11: 1 7 5 3 11 NA
12: 8 4 6 7 12 TRUE
13: 9 5 3 9 13 NA
14: 10 3 8 2 14 NA
[1] 7
from to distance weight rn drop
1: 7 8 2 1 7 TRUE
[1] 8
from to distance weight rn drop
1: 4 3 5 6 8 TRUE
[1] 9
from to distance weight rn drop
1: 2 1 1 7 9 NA
from to distance weight rn drop
1: 1 8 1 10 1 FALSE
2: 2 6 1 9 2 FALSE
3: 3 4 1 5 3 FALSE
4: 4 5 3 9 4 TRUE
5: 5 6 4 8 5 TRUE
6: 6 2 5 2 6 FALSE
7: 7 8 2 1 7 TRUE
8: 4 3 5 6 8 TRUE
9: 2 1 1 7 9 FALSE
10: 6 8 4 8 10 TRUE
11: 1 7 5 3 11 NA
12: 8 4 6 7 12 TRUE
13: 9 5 3 9 13 NA
14: 10 3 8 2 14 NA
[1] 10
from to distance weight rn drop
1: 6 8 4 8 10 TRUE
[1] 11
from to distance weight rn drop
1: 1 7 5 3 11 NA
from to distance weight rn drop
1: 1 8 1 10 1 FALSE
2: 2 6 1 9 2 FALSE
3: 3 4 1 5 3 FALSE
4: 4 5 3 9 4 TRUE
5: 5 6 4 8 5 TRUE
6: 6 2 5 2 6 FALSE
7: 7 8 2 1 7 TRUE
8: 4 3 5 6 8 TRUE
9: 2 1 1 7 9 FALSE
10: 6 8 4 8 10 TRUE
11: 1 7 5 3 11 FALSE
12: 8 4 6 7 12 TRUE
13: 9 5 3 9 13 NA
14: 10 3 8 2 14 NA
[1] 12
from to distance weight rn drop
1: 8 4 6 7 12 TRUE
[1] 13
from to distance weight rn drop
1: 9 5 3 9 13 NA
from to distance weight rn drop
1: 1 8 1 10 1 FALSE
2: 2 6 1 9 2 FALSE
3: 3 4 1 5 3 FALSE
4: 4 5 3 9 4 TRUE
5: 5 6 4 8 5 TRUE
6: 6 2 5 2 6 FALSE
7: 7 8 2 1 7 TRUE
8: 4 3 5 6 8 TRUE
9: 2 1 1 7 9 FALSE
10: 6 8 4 8 10 TRUE
11: 1 7 5 3 11 FALSE
12: 8 4 6 7 12 TRUE
13: 9 5 3 9 13 FALSE
14: 10 3 8 2 14 NA
[1] 14
from to distance weight rn drop
1: 10 3 8 2 14 NA
from to distance weight rn drop
1: 1 8 1 10 1 FALSE
2: 2 6 1 9 2 FALSE
3: 3 4 1 5 3 FALSE
4: 4 5 3 9 4 TRUE
5: 5 6 4 8 5 TRUE
6: 6 2 5 2 6 FALSE
7: 7 8 2 1 7 TRUE
8: 4 3 5 6 8 TRUE
9: 2 1 1 7 9 FALSE
10: 6 8 4 8 10 TRUE
11: 1 7 5 3 11 FALSE
12: 8 4 6 7 12 TRUE
13: 9 5 3 9 13 FALSE
14: 10 3 8 2 14 FALSE
Результат пока отличается от ожидаемого результата
result <- DT[!(drop)]
result
from to distance weight rn drop
1: 1 8 1 10 1 FALSE
2: 2 6 1 9 2 FALSE
3: 3 4 1 5 3 FALSE
4: 6 2 5 2 6 FALSE
5: 2 1 1 7 9 FALSE
6: 1 7 5 3 11 FALSE
7: 9 5 3 9 13 FALSE
8: 10 3 8 2 14 FALSE
Строки с 1 по 3, 11, 13 и 14 соответствуют ожидаемому результату, но строки 6 и 9 сохраняются здесь, потому что значения 2
и 1
являются уникальными в столбце to
.
Очевидно, что этот подход необходимо усовершенствовать, поскольку 2
и 1
уже появились в столбце from
строк 1 и 2, соответственно. Эти строки необходимо удалить как дубликаты.
Чтобы удалить их, result
преобразуется из широкого в длинный формат и упорядочивается по номеру строки:
ldt <- melt(result, "rn", c("to", "from"))[order(rn)]
ldt
rn variable value
1: 1 to 8
2: 1 from 1
3: 2 to 6
4: 2 from 2
5: 3 to 4
6: 3 from 3
7: 6 to 2
8: 6 from 6
9: 9 to 1
10: 9 from 2
11: 11 to 7
12: 11 from 1
13: 13 to 5
14: 13 from 9
15: 14 to 3
16: 14 from 10
Теперь нам нужно определить номера строк дубликатов, которые относятся к single_to
значениям:
ldt[duplicated(value) & variable == "to" & value %in% single_to]
rn variable value
1: 6 to 2
2: 9 to 1
Эти строки удалены из result
от anti-join :
result2 <-
result[!ldt[duplicated(value) & variable == "to" & value %in% single_to], on = .(rn)]
result2
from to distance weight rn drop
1: 1 8 1 10 1 FALSE
2: 2 6 1 9 2 FALSE
3: 3 4 1 5 3 FALSE
4: 1 7 5 3 11 FALSE
5: 9 5 3 9 13 FALSE
6: 10 3 8 2 14 FALSE
Теперь это почти соответствует ожидаемому результату. Только правило 4 должно быть реализовано. Для этого используется тот же подход, что и раньше: изменение формы на длинный, определение номеров строк и объединение. Однако здесь используется объединение обновлений :
ldt2 <- melt(unique(result2, by = "from"), "rn", c("to", "from"))[order(rn)]
result2[ldt2[duplicated(value)], on = .(rn), c("to", "distance") := NA_integer_]
result2
from to distance weight rn drop
1: 1 8 1 10 1 FALSE
2: 2 6 1 9 2 FALSE
3: 3 4 1 5 3 FALSE
4: 1 7 5 3 11 FALSE
5: 9 5 3 9 13 FALSE
6: 10 NA NA 2 14 FALSE
Обсуждение
Это решение не претендует на эффективность с точки зрения скорости кодирования или исполнения. Он просто нацелен на воспроизведение ожидаемого результата из данного набора данных.
Это требует гораздо большего тестирования. Например, OP запросил в правиле 3
Я хочу повторять этот процесс до тех пор, пока все уникальные значения от и до не появятся по крайней мере один раз в одном из столбцов
Реализуя правила 1 и 2, мы не проверяем, наконец, выполнено ли это условие.
Кроме того, я считаю, что могут быть и другие способы достижения той же цели.