Как найти, какие элементы одного набора находятся в другом наборе?

#r

#r

Вопрос:

У меня есть два набора: A со столбцами x, y и B также со столбцами x, y. Мне нужно найти индекс строк A, которые находятся внутри B (оба x и y должны совпадать). Я придумал простое решение (см. Ниже), но это сравнение находится внутри цикла и paste добавляет гораздо больше дополнительного времени.

 B <- data.frame(x = sample(1:1000, 1000), y = sample(1:1000, 1000))
A <- B[sample(1:1000, 10),]
#change some elements
A$x[c(1,3,7,10)] <- A$x[c(1,3,7,10)]   0.5

A$xy <- paste(A$x, A$y, sep='ZZZ')
B$xy <- paste(B$x, B$y, sep='ZZZ')
indx <- which(A$xy %in% B$xy)
indx
 

Например, для одного наблюдения альтернатива paste почти в 3 раза быстрее

     ind <- sample(1:1000, 1)
    xx <- B$x[ind]
    yy <- B$y[ind]

    ind <- which(with(B, x==xx amp; y==yy))
    # [1] 0.0160000324249268 seconds
    xy <- paste(xx,'ZZZ',yy, sep='')
    ind <- which(B$xy == xy)
    # [1] 0.0469999313354492 seconds
 

Комментарии:

1. Если столбцы, которые вы сопоставляете, имеют целочисленное или символьное значение, data.table пакет может предложить решение. Это намного быстрее для многих операций сопоставления и индексирования типов.

Ответ №1:

Как насчет использования merge() для сопоставления для вас?

 A$id <- seq_len(nrow(A))
sort(merge(A, B)$id)
# [1] 2 4 5 6 8 9
 

Редактировать:

Или, чтобы избавиться от двух ненужных сортировок, используйте sort= опцию merge()

 merge(A, B, sort=FALSE)$id
# [1] 2 4 5 6 8 9
 

Комментарии:

1. @ilya Это лучше. Вероятно, вы могли бы также сделать что-то вроде which(tail(duplicated(rbind(B,A)),nrow(A))) , но это может быть медленным.

2. Это работает, но, к сожалению, экономия времени не достигается. 0,0309 сек для вставки, против 0,0469 сек для этого метода. Я работаю над проектом моделирования. Около 40 минут реальной жизни заняли у меня 24 часа. Я пытаюсь повысить производительность. У меня осталось 9 часов. Из профилирования я вижу, что эта часть занимает много времени, поэтому я пытаюсь найти быструю альтернативу.

3. Ну, все еще может быть экономия времени. Мне не нужно делать вставку на B. Это может сэкономить мне время. Я проведу дополнительное тестирование

4. Да — использование merge() для этого одного побочного эффекта должно быть излишним, если вы стремитесь к скорости. Тем не менее, код в merge.data.frame() может быть хорошим источником идей. Вероятно, авторы столкнулись только с вопросами скорости, с которыми вы сталкиваетесь прямо сейчас. Дайте нам знать, что вы найдете!

5. Почему-то это звучит как проблема, которую хэш-таблицы должны быстро решать. К сожалению, все, что я знаю о хеш-таблицах, — это их название. Кто-нибудь может здесь помочь?