Я пытаюсь использовать R для фильтрации кадра данных на основе двух столбцов, чтобы выбрать строки, которые не зависят от того, в каком столбце из этих двух столбцов находится значение.
Ввод выглядит следующим образом: дубликаты выделены жирным шрифтом. Обратите внимание, что столбец ID
НЕ способствует уникальности:
Я попытался отфильтровать, удалив строки на основе значений Col_2
, которые не отображаются в Col_1
, или наоборот, но это удаляет слишком много. Я бы хотел, чтобы результат был примерно таким:
Я не могу поменять местами значения между Col_1
и Col_2
, потому что в тех случаях, когда нет «дублирования», важно, в каком столбце появляется данное значение. Также не имеет значения, выбран ли, например, A B
вместо B A
, просто сохраняется только один.
Любопытно увидеть более краткие подходы. Мы могли бы поворачивать дольше, сортировать и комбинировать записи, чтобы определить отдельные:
library(tidyverse)
tibble::tribble(
~ID, ~Col_1, ~Col_2,
1L, "A", "A",
1L, "A", "B",
1L, "A", "C",
1L, "B", "A",
1L, "B", "B",
1L, "B", "C",
2L, "C", "B",
2L, "C", "C",
2L, "C", "D"
) |>
mutate(row = row_number()) |>
pivot_longer(-c(row, ID)) |>
arrange(ID, value) |>
summarize(vals = paste(value, collapse = ", "), .by = c(ID, row)) |>
distinct(vals, .keep_all = TRUE)
Результат
ID row vals
<int> <int> <chr>
1 1 1 A, A
2 1 2 A, B
3 1 3 A, C
4 1 5 B, B
5 1 6 B, C
6 2 8 C, C
7 2 9 C, D
Один из способов решения вашей проблемы:
library(dplyr)
df |>
distinct(C1 = pmin(Col_1, Col_2), C2 = pmax(Col_1, Col_2), .keep_all=T) |>
select(-c(C1, C2))
ID Col_1 Col_2
1 1 A A
2 1 A B
3 1 A C
4 1 B B
5 1 B C
6 2 C C
7 2 C D
Или используя встроенные функции:
with(df, df[!duplicated(cbind(pmin(Col_1, Col_2), pmax(Col_1, Col_2))),])
Сравниваем имеющиеся комбинации с комбинациями, созданными gtools::combinations
. Если мы разрешим повторы («AA», «BB» и т. д.), мы получим желаемый результат.
library(dplyr)
library(gtools)
df %>%
filter(paste0(Col_1, Col_2) %in% apply(
combinations(n = length(unique(c(Col_1, Col_2))),
r = 2,
v = unique(c(Col_1, Col_2)),
repeats.allowed = TRUE), 1, paste, collapse = ""))
ID Col_1 Col_2
1 1 A A
2 1 A B
3 1 A C
4 1 B B
5 1 B C
6 2 C C
7 2 C D
df <- structure(list(ID = c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L), Col_1 = c(
"A", "A", "A", "B", "B", "B", "C", "C", "C"), Col_2 = c("A", "B",
"C", "A", "B", "C", "B", "C", "D")), class = "data.frame", row.names = c(NA,
-9L))