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

Рассмотрим фрейм данных Data, созданный здесь:

Data <- data.frame(Location = rep(letters[1:20], each = 10))

Я хочу делать попарные сравнения вручную. Во-первых, я хочу найти все возможные попарные комбинации между уровнями Location в Data, поэтому я делаю объект Pairs таким:

Pairs <-expand.grid(unique(Data$Location),unique(Data$Location))

Теперь я хочу удалить строки из объекта Pairs, где Pairs$Var1 == Pairs$Var2, и я хочу удалить строки, которые являются дубликатами предыдущих пар, но в обратном порядке. Другими словами, я хочу удалить строки, где Pairs$Var1 == a и Pairs$Var2 == a, Pairs$Var1 == b и Pairs$Var2 == b и так далее (т. е. я не хочу сравнивать Locations сами с собой), и я также не хочу, чтобы одно и то же сравнение выполнялось дважды. , так что если Var1==a уже сравнивалось (или уже существует ранее в data.frame) с Var2 == b, то я не хочу сравнивать Var1 == b с Var2 == a, поэтому мне нужно удалить одну из этих комбинаций, но не другую (я надеюсь, это имеет смысл). Как я могу это сделать?

Мы можем использовать Pairs[Pairs$Var1 == Pairs$Var2,], чтобы увидеть, где Var1 == Var2, но это не поможет решить вторую проблему.


person Ryan    schedule 08.07.2020    source источник
comment
Делает ли Pairs[Pairs$Var1 < Pairs$Var2,] то, что вы хотите? В зависимости от ваших настроек stringsAsFactors вам может понадобиться Pairs[as.character(Pairs$Var1) < as.character(Pairs$Var2),]   -  person Bas    schedule 08.07.2020
comment
@Bas Pairs[as.character(Pairs$Var1) < as.character(Pairs$Var2),] делает то, что я хочу, хотя я не совсем понимаю, почему, не могли бы вы уточнить в ответе? Таким образом, я также могу принять ваш ответ. Кроме того, как я могу удалить эти строки из Pairs, не создавая новый объект? Я пробовал такие вещи, как: Pairs <- Pairs[-c(as.character(Pairs$Var1) < as.character(Pairs$Var2)),], но у меня ничего не получилось   -  person Ryan    schedule 08.07.2020


Ответы (2)


Чтобы убедиться, что два столбца различны и что нет симметричных дубликатов, можно использовать изящный прием, используя оператор «больше чем» или «меньше чем».

Pairs <- Pairs[as.character(Pairs$Var1) < as.character(Pairs$Var2),]

или, если вы хотите обратное,

Pairs <- Pairs[as.character(Pairs$Var1) >= as.character(Pairs$Var2),]

Это работает, потому что a < a — это False (элемент не меньше самого себя), и для каждой пары (a, b) либо a < b, либо b < a есть True, а другая — False. Таким образом, для каждой такой пары вы сохраните только одну.

Поэтому as.character(Pairs$Var1) < as.character(Pairs$Var2) возвращает вектор True и False, который вы можете использовать для нарезки вашего data.frame. as.character() необходимо, потому что нельзя сравнивать factors, используя <.

person Bas    schedule 09.07.2020

Я публикую решение, которое использует for:

Сначала удалите строки с одинаковым значением в обоих столбцах:

Pairs <- Pairs[Pairs$Var1 != Pairs$Var2,]

Во-вторых, удалите стандартные дубликаты:

Pairs <- Pairs[!duplicated(Pairs),]

Наконец, удалите дубликаты в обратном порядке. Моя стратегия включает в себя создание временных столбцов, которые позволяют вам (а) не производить поиск случаев, которые, как вы уже знаете, являются дубликатами; (b) произвести окончательную фильтрацию. Затем вы можете удалить временный столбец:

Pairs$my_duplicated <- FALSE
for(i in 1:nrow(Pairs)){
  if(Pairs$my_duplicated[i] == FALSE){
    my_test <- Pairs$Var2 %in% Pairs$Var1[i] & Pairs$Var1 %in% Pairs$Var2[i]
    Pairs$my_duplicated[my_test] <- TRUE
  }
}
Pairs <- Pairs[!Pairs$my_duplicated,]
Pairs$my_duplicated <- NULL
person carlo_sguera    schedule 08.07.2020