Выбор уникальных строк кадра данных, когда повторяющиеся значения меняются местами в нескольких столбцах в R?

Я пытаюсь использовать R для фильтрации кадра данных на основе двух столбцов, чтобы выбрать строки, которые не зависят от того, в каком столбце из этих двух столбцов находится значение.

Ввод выглядит следующим образом: дубликаты выделены жирным шрифтом. Обратите внимание, что столбец ID НЕ способствует уникальности:

ИДЕНТИФИКАТОР Столбец_1 Столбец_2 1 А А 1 А Б 1 А С 1 Б А 1 Б Б 1 Б С 2 С Б 2 С С 2 С Д

Я попытался отфильтровать, удалив строки на основе значений Col_2, которые не отображаются в Col_1, или наоборот, но это удаляет слишком много. Я бы хотел, чтобы результат был примерно таким:

ИДЕНТИФИКАТОР Столбец_1 Столбец_2 1 А А 1 А Б 1 А С 1 Б Б 1 Б С 2 С С 2 С Д

Я не могу поменять местами значения между Col_1 и Col_2, потому что в тех случаях, когда нет «дублирования», важно, в каком столбце появляется данное значение. Также не имеет значения, выбран ли, например, A B вместо B A, просто сохраняется только один.


54
3

Ответы:

Любопытно увидеть более краткие подходы. Мы могли бы поворачивать дольше, сортировать и комбинировать записи, чтобы определить отдельные:

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))