Подтвердить что ты не робот

Найти повторяющиеся значения в 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), выведет стог сена на ваш экран в которые вам не удастся найти какие-либо редкие повторяющиеся иглы.

4b9b3361

Ответ 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-решения для работы с простыми векторами, такими как идентификаторы.