Ответ 1
Поскольку, кажется, большой интерес в ответе на этот вопрос, я думал, что напишу альтернативный метод регулярных выражений для потомков.
Используя функцию "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: Запишите их во все соответствующие местоположения в исходном векторе.
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. Мы конкатенируем ("вставляем") эти последовательности, используя параметр "свернуть", если есть несколько совпадений. Затем мы используем вторую конкатенацию, чтобы поместить последовательности внутри функции comb (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
Обновление: я понял, что исходная проблема говорит, что она соответствует одному-трем нулям подряд, а не "двум или более", которые я написал в исходном коде. Я обновил регулярные выражения и объяснение, хотя код остается тем же.