2015-12-07 7 views
1

У меня есть образец целых чисел в качестве c(1,2,3,4,5), который должен быть приблизительно соответствует в данном, как c(1,10,1,6,3,4,5,1,2,3,4,5,9,10,1,2,3,4,6)Приближенного сопоставления с образцом в последовательности целочисленных данных и экстракции с помощью R

Я попробовал:

  • pmatch()
  • all.equal()
  • grepl()

, но они, похоже, не поддерживают этот сценарий.

pattern <- c(1,2,3,4,5) 

data <- c(1,10,1,6,3,4,5,1,2,3,4,5,9,10,1,2,3,4,6) 

В приведенном выше примере мне нужно произвести следующий вывод:

1,6,3,4,5

1,2,3,4,5

1,2 , 3,4,6

Оцените любые мысли по этому вопросу.

Благодаря

+1

Как вы получаете эти результаты неясно. Пожалуйста, объясните, что вы делаете, чтобы перейти от входов к выходам. –

+0

@RichardScriven - это ужасно непонятно, но похоже, что оно соответствует наборам, т. Е. Удаляет первую партию ближайших совпадений, а затем запускается снова. '1: 5' соответствует' 1,6,3,4,5' довольно близко, затем '1,2,3,4,5', затем' 1,2,3,4,6' – thelatemail

+0

Пример приблизительной версии из этого: http://stackoverflow.com/questions/33027611/how-to-index-a-vector-sequence-within-a-vector-sequence/33028695 – thelatemail

ответ

2

Я думаю, что вы говорите «соответствуют последовательности целых чисел в другой последовательности целых чисел, где, по крайней мере N-1 в матче целых чисел». Непонятно, какое поведение должно быть в случае совпадающих совпадений, поэтому следующее будет отображать последовательности, которые перекрываются.

# helper function to test "match" at a threshold of 4 matches 
is_almost <- function(s1, s2, thresh = 4) { 
    sum(s1 == s2) >= thresh } 

# function to lookup and return sequences 
extract_seq <- function(pattern, data) { 
    res <- lapply(1:(length(data) - length(pattern) + 1), function(s) { 
    subseq <- data[s:(s+length(pattern)-1)] 
    if (is_almost(pattern, subseq)) { 
     subseq} 
    }) 
    Filter(Negate(is.null),res) 
} 

# let's test it out 
pattern <- c(1,2,3,4,5) 
data <- c(1,10,1,6,3,4,5,1,2,3,4,5,9,10,1,2,3,4,6) 

extract_seq(pattern,data) 

[[1]] 
[1] 1 6 3 4 5 

[[2]] 
[1] 1 2 3 4 5 

[[3]] 
[1] 1 2 3 4 6 
+1

Спасибо Гэри, что вы предоставили, это то, что я искал. – Nasir

+1

Я попробовал решение Гэри с числовым вектором (данными) размером 500 тысяч. Результаты потребовали всего 6 секунд. – Nasir

0

Если вы хотите, чтобы найти уникальные элементы в векторе, соответствующий заданный вектор можно использовать %Iin%, чтобы проверить наличие вашего «шаблон» в более широком векторе. Оператор, %in%, возвращает логический вектор. Передача этого вывода в which() возвращает индекс каждого значения TRUE, который может использоваться для подмножества большего вектора, чтобы возвращать все элементы, которые соответствуют «шаблону», независимо от порядка. Передача вектора подмножества в unique() устраняет дубликаты, так что есть только одно появление каждого элемента из большего вектора, который соответствует элементам и длине вектора «шаблон».

Например:

> num.data <- c(1, 10, 1, 6, 3, 4, 5, 1, 2, 3, 4, 5, 9, 10, 1, 2, 3, 4, 5, 6) 
> num.pattern.1 <- c(1,6,3,4,5) 
> num.pattern.2 <- c(1,2,3,4,5) 
> num.pattern.3 <- c(1,2,3,4,6) 
> unique(num.data[which(num.data %in% num.pattern.1)]) 
[1] 1 6 3 4 5 
> unique(num.data[which(num.data %in% num.pattern.2)]) 
[1] 1 3 4 5 2 
> unique(num.data[which(num.data %in% num.pattern.3)]) 
[1] 1 6 3 4 2 

Обратите внимание, что первый результат соответствует порядку num.pattern.1 совпадением. Остальные два вектора не соответствуют порядку векторов шаблона.

Чтобы найти точную последовательность в пределах num.data, который соответствует модели вы можете использовать что-то подобное следующую функцию:

set.seed(12102015) 
test.data <- sample(c(1:99), size = 500, replace = TRUE) 
test.pattern.1 <- test.data[90:94] 

find_vector <- function(test.data, test.pattern.1) { 
    # List of all the vectors from test.data with length = length(test.pattern.1), currently empty 
    lst <- vector(mode = "list") 
    # List of vectors that meet condition 1, currently empty 
    lst2 <- vector(mode = "list") 
    # List of vectors that meet condition 2, currently empty 
    lst3 <- vector(mode = "list") 
    # A modifier to the iteration variable used to build 'lst' 
    a <- length(test.pattern.1) - 1 
    # The loop to iterate through 'test.data' testing for conditions and building lists to return a match 
    for(i in 1:length(test.data)) { 
    # The list is build incrementally as 'i' increases 
    lst[[i]] <- test.data[c(i:(i+a))] 
    # Conditon 1 
    if(sum(lst[[i]] %in% test.pattern.1) == length(test.pattern.1)) {lst2[[i]] <- lst[[i]]} 
    # Condition 2 
    if(identical(lst[[i]], test.pattern.1)) {lst3[[i]] <- lst[[i]]} 
    } 
    # Remove nulls from 'lst2' and 'lst3' 
    lst2 <- lst2[!sapply(lst2, is.null)] 
    lst3 <- lst3[!sapply(lst3, is.null)] 
# Return the intersection of 'lst2' and 'lst3' which should be a match to the pattern vector. 
return(intersect(lst2, lst3)) 
} 

Для воспроизводимости я использовал set.seed(), а затем создал набор тестовых данных и шаблон. Функция find_vector() принимает два аргумента: во-первых, test.data, который является большим числовым вектором, который вы хотите проверить для векторов рисунков, а во-вторых, test.pattern.1, что является более коротким числовым вектором, который вы хотите найти в test.data.Сначала создаются три списка: lst для хранения test.data, разделенных на меньшие векторы длины, равные длине вектора шаблона, lst2 для хранения векторов шаблона от lst, удовлетворяющих первому условию, и lst3 для хранения от lst векторов, которые удовлетворяют второе условие. Первое условие проверяет, что элементы векторов в lst находятся в векторе шаблона. Второе условие проверяет, что вектор от lst соответствует вектору шаблона по порядку и по элементу.

Одна из проблем с этим подходом заключается в том, что значения NULL вводятся в каждый список, когда условия не выполняются, но процесс останавливается, когда условия выполняются. Для справки вы можете распечатать списки, чтобы просмотреть все проверенные векторы, векторы, соответствующие первому условию, и векторы, соответствующие второму условию. Нули могут быть удалены. При удалении нулей поиск пересечения lst2 и lst3 покажет шаблон, идентичный тождественно в test.data.

Для использования функции обязательно укажите test.data <- 'a numeric vector' и test.pattern.1 <- 'a numeric vector'. Никаких специальных пакетов не требуется. Я не проводил бенчмаркинга, но функция работает быстро. Я также не искал сценарии, в которых функция не срабатывала.