R — Повторения массива в другом массиве

#r

#r

Вопрос:

Из фрейма данных я получаю новый массив, вырезанный из фрейма данных. Я хочу получить количество раз, когда в нем появляется определенное повторение.

Например

 main <- c(A,B,C,A,B,V,A,B,C,D,E)
p <- c(A,B,C)
q <- c(A,B)

someFunction(main,p)
2

someFunction(main,q)
3
  

Я немного повозился с rle , но он также учитывает каждое повторение, незначительное.

Есть ли быстрое решение, которого мне не хватает?

Ответ №1:

Вы можете использовать один из инструментов регулярных выражений в R, поскольку это действительно упражнение по сопоставлению с шаблоном, специально gregexpr для этого вопроса. p И q векторы представляют шаблон поиска, и main именно там мы хотим искать эти шаблоны. Со страницы справки для gregexpr :

 gregexpr returns a list of the same length as text each element of which is of 
the same form as the return value for regexpr, except that the starting positions 
of every (disjoint) match are given. 
  

Таким образом, мы можем взять длину первого списка, возвращаемого gregexpr , который дает начальные позиции совпадений. Сначала мы свернем векторы, а затем выполним поиск:

 someFunction <- function(haystack, needle) {
    haystack <- paste(haystack, collapse = "")
    needle <- paste(needle, collapse = "")
    out <- gregexpr(needle, haystack)
    out.length <- length(out[[1]])
    return(out.length)
}

> someFunction(main, p)
[1] 2
> someFunction(main, q)
[1] 3
  

Примечание — вам также нужно добавить «» вокруг вашего вектора main , p и q векторов, если у вас не определены переменные A, B, C и др.

 main <- c("A","B","C","A","B","V","A","B","C","D","E")
p <- c("A","B","C")
q <- c("A","B")
  

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

1. Красиво, и это работает с данными примера. Но это может сработать не со всеми входными данными из-за вашего сворачивания. Что происходит, когда вы хотите выполнить поиск c(1,2,3) в c(1,2,3,123) ?

2. Хороший вызов. К счастью, я не могу получить этот ввод, но это действительно проблема.

3. Решение @ Chase должно сработать, если вы сворачиваете, используя (скажем) «.» вместо «».

4. Да, но тогда вы предполагаете, что ваша строка поиска никогда не будет содержать «.». В общем, я крайне осторожно отношусь к решениям, которые включают преобразование данных. Да, иногда этого трудно избежать, но не в этом случае.

5. @Andrie — итак, каков ожидаемый результат во втором примере?

Ответ №2:

Я не уверен, что это лучший способ, но вы можете просто выполнить эту работу с помощью:

 f <- function(a,b) 
  if (length(a) > length(b)) 0 
  else all(head(b, length(a)) == a)   Recall(a, tail(b, -1))
  

Кто-то может найти, а может и не найти встроенную функцию.

Ответ №3:

Используя sapply :

 find_x_in_y <- function(x, y){
  sum(sapply(
      seq_len(length(y)-length(x)),
      function(i)as.numeric(all(y[i:(i length(x)-1)]==x))
  ))
}


find_x_in_y(c("A", "B", "C"), main)
[1] 2

find_x_in_y(c("A", "B"), main)
[1] 3
  

Ответ №4:

Вот способ сделать это с помощью embed(v,n) , который возвращает матрицу всех подпоследовательностей векторной n длины v :

 find_x_in_y <- function(x, y) 
                   sum( apply( embed( y, length(x)), 1, 
                                  identical, rev(x)))

> find_x_in_y(p, main)
[1] 2
> find_x_in_y(q, main)
[1] 3