Удаление дубликатов всех комбинаций при сохранении всех столбцов
Мне нужно удалить повторяющиеся комбинации двух столбцов (feedID и feedID2) внутри групп (ID), сохраняя при этом большое количество других столбцов в наборе данных. Все строки с дубликатами должны быть удалены, будь то A в столбце 2 и B в столбце 3 или наоборот. Кроме того, я хотел бы удалить все строки, где есть, например, A в обоих столбцах или где есть NA в одном из столбцов. Я не могу отсортировать данные по столбцам, т. Е. Если A находится в столбце № 2, он должен остаться в столбце № 2.
Я знаю, что это может показаться дублирующим вопросом, но ни один из других ответов, похоже, не работает с моим набором данных или не запрашивает то же самое. Например, поиск уникальных комбинаций независимо от позиции. Удаление дубликатов комбинаций в R (независимо от порядка).
test <- data.frame(ID= c("49V", "49V","49V", "49V", "49V", "52V", "52V", "52V"),
feedID = c("A1", "A1", "G2", "A1", "G2", "B1", "D1", "D2" ),
feedID2 = c("A1", "G2", "A1", "G2", "NA", "D1", "D2", "NA" ))
desiredoutput <- data.frame(ID= c("49V", "52V", "52V"),
feedID = c("A1","B1", "D1" ),
feedID2 = c("G2", "D1", "D2" ))
следующий код не удаляет дубликаты, если в разных столбцах
test2 <- test [!duplicated(test[,c("ID","feedID", "feedID2")]),]
этот код вообще ничего не делает, но не выдает ошибки
test2 <- test%>% distinct(1,2,3) # where numbers refer to the columns
этот код выдает ошибку, которая для dimnames, не уверен, что это значит. Я не получаю это с моими тестовыми данными, я не уверен, почему и не могу воспроизвести ошибку...
indx <- !duplicated(t(apply(test, 1, sort))) # finds non - duplicates in sorted rows
test[indx, ]
Есть идеи?
3 ответа
Вот базовое решение, используя complete.cases
функция, а также создание отсортированного feedID
колонка:
# remove any rows with NA values
test <- test[complete.cases(test[,c('ID', 'feedID','feedID2')]),]
#remove any rows with feedID == feedID2
test <- test[!(test$feedID == test$feedID2),]
# add new feedID3 column
test$feedID3 <- apply(test, 1, function(x) paste(sort(c(x[2], x[3])), collapse = '-'))
# remove any duplicates, and remove last column
test[!duplicated(test[,c('feedID3', 'ID')]), -4]
ID feedID feedID2
2 49V A1 G2
6 52V B1 D1
7 52V D1 D2
данные
Обратите внимание, что мы преобразовали "NA"
в NA
и мы также установили stringsAsFactors = TRUE
test <- data.frame(ID= c("49V", "49V","49V", "49V", "49V", "52V", "52V", "52V"),
feedID = c("A1", "A1", "G2", "A1", "G2", "B1", "D1", "D2" ),
feedID2 = c("A1", "G2", "A1", "G2", NA, "D1", "D2", NA ),
stringsAsFactors = FALSE)
Ваши данные снова, но с "NA"
изменился на NA
а также stringsAsFactors=F
test <- data.frame(ID= c("49V", "49V","49V", "49V", "49V", "52V", "52V", "52V"),
feedID = c("A1", "A1", "G2", "A1", "G2", "B1", "D1", "D2" ),
feedID2 = c("A1", "G2", "A1", "G2", NA, "D1", "D2", NA ),
stringsAsFactors=F)
library(dplyr)
test %>%
filter(complete.cases(.)) %>% # Remove rows with NA
rowwise() %>% # Perform next step by row
mutate(dup=paste0(sort(c(feedID,feedID2)),collapse="")) %>% # Sort and combine feedID and feedID2
ungroup() %>%
group_by(ID) %>% # Remove rowwise grouping
mutate(dup=duplicated(dup)) %>% # Find duplicated feedID:feedID2 pairs
filter(dup==F) %>% # Remove duplicated pairs
filter(!(feedID==feedID2)) %>% # Remove where feedID == feedID2
select(-dup) # Remove dummy column
ID feedID feedID2
1 49V A1 G2
2 52V B1 D1
3 52V D1 D2
Если вы хотите только искать NA
в feedID
& feedID2
замещать filter(complete.cases(.))
с filter(!is.na(feedID) & !is.na(feedID2))
После изменения "NA" на NA и установки строки AsFactors = F
library(dplyr)
library(stringr)
test <- data.frame(ID= c("49V", "49V","49V", "49V", "49V", "52V", "52V", "52V"),
feedID = c("A1", "A1", "G2", "A1", "G2", "B1", "D1", "D2" ),
feedID2 = c("A1", "G2", "A1", "G2", NA, "D1", "D2", NA ),
stringsAsFactors = F)
desiredoutput <- data.frame(ID= c("49V", "52V", "52V"),
feedID = c("A1","B1", "D1" ),
feedID2 = c("G2", "D1", "D2" ),
stringsAsFactors = F)
test %>%
# Remove NAs and all rows where the IDs are equal
filter(!is.na(feedID),
!is.na(feedID2),
feedID != feedID2) %>%
# Group rowwise and create a sorted pair of the two ID columns
rowwise() %>%
mutate(revCheck = str_c(str_sort(c(feedID, feedID2)), collapse = "")) %>%
ungroup() %>%
# Find distinct ID pairs and keep all variables
distinct(revCheck,
.keep_all = T) %>%
# Find distinct rows for each ID pair. I kept these separate because I
# think that's what you're asking for in your example, you want all
# duplicates in feedID and all duplicates in feedID2 removed, not just
# duplicate combinations of feedID and feedID2. See .keep_all in ?distinct
distinct(feedID,
.keep_all = T) %>%
distinct(feedID2,
.keep_all = T) %>%
# Remove the sorted pair id
select(-revCheck) %>%
# Return a dataframe
as.data.frame(.)