2017-01-09 57 views
7

在下面的例子中,我想知道010序列的數量,或者1010序列的數量。以下是一個可行的例子;如何計算兩個觀察二進制組合的數量?

x <- c(1,0,0,1,0,0,0,1,1,1,0,0,1,0,1,0,1,0,1,0,1,0) 

在這個例子中,010序列的數量將是6和1010序列的數量將是4。

什麼。將計數連續序列的數目的最有效的/簡單的方法?

+0

這適用於第一種情況'sum(diff(diff(x))== -2)',但有人可以檢查它是否在任何地方失敗。 –

回答

7

另一種解決辦法是這樣的:

library(stringr) 
x <- c(1,0,0,1,0,0,0,1,1,1,0,0,1,0,1,0,1,0,1,0,1,0) 
xx = paste0(x, collapse = "") 
str_count(xx, '(?<=010)') 
[1] 6 

str_count(xx, '(?<=1010)') 
[1] 4 

由於@Pierre Lafortune在這是可以做到的評論指出,不使用任何套餐:

length(gregexpr("(?<=010)", xx, perl=TRUE)[[1]]) 
[1] 6 
+0

嘿,這很酷!我很快就需要學習這個軟件包! :)我正忙着嘗試使用base R –

+0

@ joel.wilson,這對於計算這樣的事情非常方便。 – Kristofersen

+3

這兩種情況下的輸出都不正確 –

5

邏輯:取一個你正在搜索的模式長度的substr並將其與該模式進行比較。

xx = paste0(x, collapse = "") 
# [1] "1001000111001010101010" 
# case 1 : 
xxx = "010" 
sum(sapply(1:(length(x)-nchar(xxx)+1), function(i) substr(xx,i,i+nchar(xxx)-1)==xxx)) 
# [1] 6 

# case 2 : 
xxx = "1010" 
# [1] 4 
10

斷線的方式:

f = function(x, patt){ 
    if (length(x) == length(patt)) return(as.integer(x == patt)) 
    w = head(seq_along(x), 1L-length(patt)) 
    for (k in seq_along(patt)) w <- w[ x[w + k - 1L] == patt[k] ] 
    w 
} 

length(f(x, patt = c(0,1,0))) # 6 
length(f(x, patt = c(1,0,1,0))) # 4 

替代品。從@ cryo11,還有一種方法:

function(x,patt) sum(apply(embed(x,length(patt)),1,function(x) all(!xor(x,patt)))) 

或另一種變化:

function(x,patt) sum(!colSums(xor(patt, t(embed(x,length(patt)))))) 

或data.table:

library(data.table) 
setkey(setDT(shift(x, seq_along(patt), type = "lead")))[as.list(patt), .N] 

(該shift功能非常相似embed。 )

+0

+1爲「無繩」方式。這裏另一個:'f = function(x,patt)sum(apply(embed(x,length(patt)),1,function(x)all(!xor(x,patt))))''。這一個不需要外部'長度'。 – cryo111

+0

@ cryo111酷,從未想過使用異或!我想還有一些方法可以通過'=='使用'embed',轉置/掃描以及列或者和。 – Frank

3

R介紹了在3.3.0中的函數。使用這種和substring,我們可以實現@ joel.wilson的方法

sum(startsWith(substring(paste(x, collapse=""), 
         head(seq_along(x), -2), tail(seq_along(x), -2)), "010")) 

這裏,substring構建三個字符相鄰集和startsWith測試如果每個這些是一樣的「010」。然後將TRUE值相加在一起。