2015-12-07 75 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萬大小的數字矢量(數據)的Gary解決方案。只需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分成等於所述模式矢量的長度,lst2lst滿足第一條件,並且lst3保持模式矢量從lst認爲滿足矢量長度的更小的載體第二個條件。第一個條件測試lst中的向量的元素是否在模式向量中。第二個條件測試來自lst的向量按順序和元素匹配模式向量。

這種方法的一個問題是當條件不滿足時NULL值被引入到每個列表中,但是當條件滿足時該過程停止。作爲參考,您可以打印列表以查看所有測試的向量,滿足第一個條件的向量以及滿足第二個條件的向量。空值可以被刪除。刪除空值後,找到lst2lst3的交集將在test.data中顯示相同匹配的模式。

要使用該功能,請確保明確定義了test.data <- 'a numeric vector'test.pattern.1 <- 'a numeric vector'。不需要特殊的軟件包。我沒有做任何基準測試,但該功能似乎工作得很快。我也沒有尋找功能會失敗的場景。