2013-06-28 54 views
4

是否可以計算R中序列的重複部分? 例如:如何計算R中一個重複的序列部分?

x<- c(1,3.0,3.1,3.2,1,1,2,3.0,3.1,3.2,4,4,5,6,5,3.0,3.1,3.2, 
     3.1,2,1,4,6,4.0,4,3.0,3.1,3.2,5,3.2,3.0,4) 

是否有可能算的序列3.0,3.1,3.2發生的時間?所以在這個例子中它必須是:4

+0

你只是想算特定子?或者您是否想要識別可能存在於您的數據中的任何其他子序列? – A5C1D2H2I1M1N2O1R2T1

+4

插入關於匹配浮點值的標準警告。除非你需要保留所有的數字,否則你可能想通過'sprintf(「%2f」,mydata)'或者等價的方式運行你的數據,這樣你就可以在字符串上進行完全匹配。 –

回答

5

我會做這樣的事情:

pattern <- c(3, 3.1, 3.2) 
len1 <- seq_len(length(x) - length(pattern) + 1) 
len2 <- seq_len(length(pattern))-1 
sum(colSums(matrix(x[outer(len1, len2, '+')], 
    ncol=length(len1), byrow=TRUE) == pattern) == length(len2)) 

PS:通過改變sumwhich你會得到每個實例的開始。

2

你可以把它變成一個字符串,並使用gregexpr

sum(gregexpr("3 3.1 3.2", paste(x, collapse=" "), fixed=TRUE)[[1]] != -1) 
[1] 4 
+1

當沒有匹配時,這會給出1的回答,因爲'gregexpr'在不匹配的情況下返回-1。 – Arun

+2

這給出了重疊序列的不正確結果:'x = c(1,2,2,2,3,2,2); s = c(2,2)' – eddi

+0

@eddi當你真的不知道OP如何處理重疊序列時,說它是「不正確的」有點愚蠢,或者事實上,如果重疊序列需要考慮在所有。 –

2

Carl Witthoft的seqle function可能對您有用。

功能如下:

seqle <- function(x,incr=1) { 
    if(!is.numeric(x)) x <- as.numeric(x) 
    n <- length(x) 
    y <- x[-1L] != x[-n] + incr 
    i <- c(which(y|is.na(y)),n) 
    list(lengths = diff(c(0L,i)), 
     values = x[head(c(0L,i)+1L,-1L)]) 
} 

適用於你的數據,它應該是這樣的:

temp <- seqle(x, incr=.1) 
temp 
# $lengths 
# [1] 1 3 1 1 1 3 1 1 1 1 1 3 1 1 1 1 1 1 1 3 1 1 1 1 
# 
# $values 
# [1] 1.0 3.0 1.0 1.0 2.0 3.0 4.0 4.0 5.0 6.0 5.0 3.0 3.1 2.0 1.0 4.0 
# [17] 6.0 4.0 4.0 3.0 5.0 3.2 3.0 4.0 

現在,我們怎麼看呢? lengths告訴我們,我們的載體有一個序列1,然後是3,然後是1,和1,以及1和3 .... values告訴我們,長度爲3的序列的第一個值是「 3.0「,下一個長度爲3的序列的第一個值是」3.0「,以此類推。

這更容易看作data.frame

data.frame(temp)[temp$lengths > 1, ] 
# lengths values 
# 2  3  3 
# 6  3  3 
# 12  3  3 
# 20  3  3 

在這個例子中,所有序列的長度是相同的,他們開始在相同的值,因此我們可以只要看看排在上面產生的data.frame數量得到你的答案。

+0

+1,儘管我不確定這是OP想要的。例如:該模式也可以是:'c(10,8,15)'。 – Arun

+0

@阿倫,真的。把它扔出去! – A5C1D2H2I1M1N2O1R2T1

+1

由於顯而易見的原因,我不得不迴避給予+1 .-)。但我很榮幸能參考我的衍生作品。 –

3

還有一個(通用移動窗口)的方法:

x <- c(1,3.0,3.1,3.2,1,1,2,3.0,3.1,3.2,4,4,5,6,5,3.0,3.1,3.2, 3.1,2,1,4,6,4.0,4,3.0,3.1,3.2,5,3.2,3.0,4) 
s <- c(3, 3.1, 3.2) 

sum(apply(embed(x, length(s)), 1, function(y) {all(y == rev(s))})) 
# [1] 4 

embed輸出明白髮生了什麼。

正如阿倫指出apply這裏是相當緩慢的,和一個可以同時使用embed與阿倫的matrix的手段來得到這是快了很多:

sum(colSums(matrix(embed(x, length(s)), 
        byrow = TRUE, nrow = length(s)) == rev(s)) == length(s)) 
+0

我首先碰到了'embed'。但是需要進行轉置的矢量掃描。或者應該使用'apply'。因此我回歸到了按行構建矩陣。 – Arun

+1

是有道理的,我剛剛測試過,當你擺脫'apply'並且執行你的'matrix'事情時,這比你的'outer'方法略快;我也會編輯該方法 – eddi