Найти повторяющиеся значения в R
У меня есть таблица с 21638 уникальными * строками:
vocabulary <- read.table("http://socserv.socsci.mcmaster.ca/jfox/Books/Applied-Regression-2E/datasets/Vocabulary.txt", header=T)
Эта таблица содержит пять столбцов, первая из которых содержит идентификационные номера респондентов. Я хочу проверить, появляются ли какие-либо респонденты дважды, или все респонденты уникальны.
Для подсчета уникальных идентификаторов я могу использовать
length(unique(vocabulary$id))
и проверить, есть ли какие-либо дубликаты, которые я мог бы сделать
length(unique(vocabulary$id)) == nrow(vocabulary)
который возвращает TRUE
, если нет дубликатов (которых нет).
Мой вопрос:
Есть ли прямой способ вернуть значения или номера строк дубликатов?
Некоторые дополнительные пояснения:
Существует проблема интерпретации с использованием функции duplicated()
, потому что она возвращает только дубликаты в строгом смысле, исключая "оригиналы". Например, sum(duplicated(vocabulary$id))
или dim(vocabulary[duplicated(vocabulary$id),])[1]
может возвращать "5" в качестве количества повторяющихся строк. Проблема в том, что если вы знаете только количество дубликатов, вы не будете знать, сколько строк они дублируют. "5" означает, что есть пять строк с одним дубликатом каждый или что есть одна строка с пятью дубликатами? И поскольку у вас не будет идентификаторов или номеров строк дубликатов, у вас не было бы средств поиска "оригиналов".
* Я знаю, что в этом опросе нет повторяющихся идентификаторов, но это хороший пример, потому что, используя любой из ответов, приведенных в другом месте этого вопроса, например duplicated(vocabulary$id)
или table(vocabulary$id)
, выведет стог сена на ваш экран в которые вам не удастся найти какие-либо редкие повторяющиеся иглы.
Ответы
Ответ 1
Вы можете использовать table
, т.е.
n_occur <- data.frame(table(vocabulary$id))
предоставляет вам фрейм данных со списком id
и количеством раз, когда они произошли.
n_occur[n_occur$Freq > 1,]
сообщает, какой id
произошло более одного раза.
vocabulary[vocabulary$id %in% n_occur$Var1[n_occur$Freq > 1],]
возвращает записи с более чем одним вхождением.
Ответ 2
Это даст вам повторяющиеся строки:
vocabulary[duplicated(vocabulary$id),]
Это даст вам количество дубликатов:
dim(vocabulary[duplicated(vocabulary$id),])[1]
Пример:
vocabulary2 <-rbind(vocabulary,vocabulary[1,]) #creates a duplicate at the end
vocabulary2[duplicated(vocabulary2$id),]
# id year sex education vocabulary
#21639 20040001 2004 Female 9 3
dim(vocabulary2[duplicated(vocabulary2$id),])[1]
#[1] 1 #=1 duplicate
ИЗМЕНИТЬ
ОК, с дополнительной информацией, вот что вам следует сделать: duplicated
имеет параметр fromLast
, который позволяет вам получать дубликаты с конца. Если вы объедините это с обычным duplicated
, вы получите все дубликаты. Следующий пример добавляет дубликаты к исходному объекту словаря (строка 1 дублируется дважды, а строка 5 дублируется один раз). Затем я использую table
, чтобы получить общее количество дубликатов на каждый идентификатор.
#Create vocabulary object with duplicates
voc.dups <-rbind(vocabulary,vocabulary[1,],vocabulary[1,],vocabulary[5,])
#List duplicates
dups <-voc.dups[duplicated(voc.dups$id)|duplicated(voc.dups$id, fromLast=TRUE),]
dups
# id year sex education vocabulary
#1 20040001 2004 Female 9 3
#5 20040008 2004 Male 14 1
#21639 20040001 2004 Female 9 3
#21640 20040001 2004 Female 9 3
#51000 20040008 2004 Male 14 1
#Count duplicates by id
table(dups$id)
#20040001 20040008
# 3 2
Ответ 3
Здесь я суммирую несколько способов, которые могут возвращать разные результаты на ваш вопрос, поэтому будьте осторожны:
# First assign your "id"s to an R object.
# Here a hypothetical example:
id <- c("a","b","b","c","c","c","d","d","d","d")
#To return ALL MINUS ONE duplicated values:
id[duplicated(id)]
## [1] "b" "c" "c" "d" "d" "d"
#To return ALL duplicated values by specifying fromLast argument:
id[duplicated(id) | duplicated(id, fromLast=TRUE)]
## [1] "b" "b" "c" "c" "c" "d" "d" "d" "d"
#Yet another way to return ALL duplicated values, using %in% operator:
id[id %in% unique(id[duplicated(id)])]
## [1] "b" "b" "c" "c" "c" "d" "d" "d" "d"
Надеюсь на эту помощь. Удачи.
Ответ 4
Здесь data.table
решение, которое будет перечислять дубликаты вместе с количеством дубликатов (будет 1, если есть 2 копии, и т.д. - вы можете настроить это в соответствии с вашими потребностями):
library(data.table)
dt = data.table(vocabulary)
dt[duplicated(id), cbind(.SD[1], number = .N), by = id]
Ответ 5
Коротко, либо с rev
:
x[!(!duplicated(x) & rev(!duplicated(rev(x))))]
... а не fromLast
:
x[!(!duplicated(x) & !duplicated(x, fromLast = TRUE))]
... и как вспомогательную функцию для предоставления логического вектора или элементов из исходного вектора:
duplicates <- function(x, as.bool = FALSE) {
is.dup <- !(!duplicated(x) & rev(!duplicated(rev(x))))
if (as.bool) { is.dup } else { x[is.dup] }
}
Обработка векторов в качестве фреймов данных для перехода на table
удобна, но может быть затруднена для чтения, а решение data.table
в порядке, но я бы предпочел базовые R-решения для работы с простыми векторами, такими как идентификаторы.