由於對這個問題的答案似乎有很多興趣,所以我想我會爲後人寫一個替代的正則表達式方法。
使用'gregexpr'函數,您可以搜索出模式並使用結果位置匹配和匹配長度來調出在原始向量中更改哪些值。使用正則表達式的好處在於,我們可以明確地確定要匹配哪些模式,因此我們不會有任何排除案例需要擔心。
注意:以下示例按書面形式工作,因爲我們假定爲單位數值。我們可以很容易地適應其他模式,但我們可以採用單個字符的小捷徑。如果我們想用可能的多位數值來做到這一點,我們希望添加一個分隔符作爲第一個連接('粘貼')功能的一部分。
守則
str.values <- paste(data, collapse="") # String representation of vector
str.matches <- gregexpr("1[0]{1,3}1", str.values) # Pattern 101/1001/10001
data[eval(parse(text=paste("c(",paste(str.matches[[1]] + 1, str.matches[[1]] - 2 + attr(str.matches[[1]], "match.length"), sep=":", collapse=","), ")")))] <- 1 # Replace zeros with ones
str.matches <- gregexpr("2[0]{1,3}2", str.values) # Pattern 202/2002/20002
data[eval(parse(text=paste("c(",paste(str.matches[[1]] + 1, str.matches[[1]] - 2 + attr(str.matches[[1]], "match.length"), sep=":", collapse=","), ")")))] <- 2 # Replace zeros with twos
步驟1:使所有的數據值的一個字符串。
str.values <- paste(data, collapse="")
# "11100112220002110102"
這倒塌下來的數據轉換成一個長字符串,所以我們可以在其上使用正則表達式。
第2步:應用正則表達式來查找字符串內任何匹配的位置和長度。
str.matches <- gregexpr("1[0]{1,3}1", str.values)
# [[1]]
# [1] 3 16
# attr(,"match.length")
# [1] 4 3
# attr(,"useBytes")
# [1] TRUE
在這種情況下,我們使用正則表達式來查找第一圖案,一到三個零([0]{2,}
)與那些在兩邊(1[0]{1,3}1
)。我們必須匹配整個模式,以防止在兩端檢查匹配的或兩個匹配的模式。我們將在下一步中將這些結果減掉。
步驟3:將1寫入原始向量中的所有匹配位置。
data[eval(parse(text=paste("c(",paste(str.matches[[1]] + 1, str.matches[[1]] - 2 + attr(str.matches[[1]], "match.length"), sep=":", collapse=","), ")")))] <- 1
# 1 1 1 1 1 1 1 2 2 2 0 0 0 2 1 1 1 1 0 2
我們在這裏一次完成了幾個步驟。首先,我們從正則表達式中匹配的數字創建數字序列列表。在這種情況下,有兩個匹配,分別從索引3和16開始,分別是4和3個項目。這意味着我們的零點位於索引(3 + 1):(3-2 + 4),或4:5和(16 + 1):(16-2 + 3)或17:17。如果有多個匹配,我們再次使用'collapse'選項連接('粘貼')這些序列。然後,我們使用第二個級聯將序列放入組合函數(c()
)中。使用'eval'和'parse'函數,我們將此文本轉換爲代碼並將其作爲索引值傳遞給[data]數組。我們寫入所有的地方。
步驟x:對每個模式重複。在這種情況下,我們需要進行第二次搜索並在兩邊找到一到三個零,然後運行與步驟3相同的語句,但分配兩個而不是一個。
str.matches <- gregexpr("2[0]{1,3}2", str.values)
# [[1]]
# [1] 10
# attr(,"match.length")
# [1] 5
# attr(,"useBytes")
# [1] TRUE
data[eval(parse(text=paste("c(",paste(str.matches[[1]] + 1, str.matches[[1]] - 2 + attr(str.matches[[1]], "match.length"), sep=":", collapse=","), ")")))] <- 2
# 1 1 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 0 2
更新:我意識到原來的問題說成一排匹配一到三個零,而不是「兩個或更多」,我寫進原代碼。我更新了正則表達式和解釋,儘管代碼保持不變。
所以,我最終選擇了這個,我喜歡對模式進行控制的能力 - 但是我很欣賞所有的建議。儘管如此,我會在不同情況下記下這些不同的方法。真的很感激它。 – 2013-04-19 11:41:49