この質問への回答に多くの関心が寄せられているように思われるので、後世のために別の正規表現方法を書き留めておこうと思いました。
'gregexpr' 関数を使用すると、パターンを検索し、結果の位置の一致と一致の長さを使用して、元のベクトルで変更する値を呼び出すことができます。正規表現を使用する利点は、一致させたいパターンを正確に明示できることです。その結果、心配する除外ケースがなくなります。
注: 次の例は、1 桁の値を想定しているため、記述どおりに機能します。他のパターンにも簡単に適応させることができますが、単一の文字を使用した小さなショートカットを使用できます。可能性のある複数桁の値でこれを行いたい場合は、最初の連結 (「貼り付け」) 関数の一部として区切り文字を追加する必要があります。
コード
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 : すべてのデータ値の 1 つの文字列を作成します。
str.values <- paste(data, collapse="")
# "11100112220002110102"
これにより、データが 1 つの長い文字列に折りたたまれるため、正規表現を使用できます。
ステップ 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
この場合、正規表現を使用して最初のパターンを探します。1 つから 3 つのゼロ ( [0]{2,}
) と両側に 1 がある ( 1[0]{1,3}1
)。両端で一致する 1 つまたは 2 つをチェックする必要がないように、パターン全体を一致させる必要があります。次のステップで、これらの両端を差し引きます。
ステップ 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 アイテムの長さの 2 つの一致があります。これは、ゼロがインデックス (3+1):(3-2+4) または 4:5 および (16+1):(16-2+3) または 17:17 にあることを意味します。複数の一致がある場合は、「collapse」オプションを使用してこれらのシーケンスを連結 (「貼り付け」) します。次に、2 番目の連結を使用して、シーケンスを結合 ( c()
) 関数内に配置します。「eval」および「parse」関数を使用して、このテキストをコードに変換し、インデックス値として [data] 配列に渡します。これらの場所にすべて 1 を書き込みます。
ステップ x : パターンごとに繰り返します。この場合、2 回目の検索を実行して、両側に 2 を持つ 1 ~ 3 個のゼロを見つけてから、ステップ 3 と同じステートメントを実行する必要がありますが、1 ではなく 2 を割り当てます。
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
更新:元のコードに書いた「2つ以上」ではなく、1つから3つのゼロが連続して一致すると言われている元の問題に気付きました。コードは同じままですが、正規表現と説明を更新しました。