Ponieważ wydaje się, że jest duże zainteresowanie odpowiedzią na to pytanie, pomyślałem, że wypiszę alternatywną metodę wyrażeń regularnych dla potomności.
Za pomocą funkcji "gregexpr" można wyszukiwać wzorce i używać wynikowych dopasowań lokalizacji i długości pasujących, aby wywołać wartości, które mają zostać zmienione w oryginalnym wektorze. Zaletą korzystania z wyrażeń regularnych jest to, że możemy dokładnie określić, które wzory chcemy dopasować, w związku z czym nie będziemy mieli żadnych przypadków wykluczenia, o które moglibyśmy się martwić.
Uwaga: Poniższy przykład działa tak, jak został napisany, ponieważ przyjmujemy wartości jednocyfrowe. Możemy łatwo dostosować go do innych wzorów, ale możemy zrobić mały skrót z pojedynczymi znakami. Jeśli chcemy to zrobić z możliwymi wielocyfrowymi wartościami, chcielibyśmy dodać znak separacji jako część pierwszej funkcji łączenia ("wklejania").
Kodeks
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
Krok 1: Złóż pojedynczy ciąg wszystkich wartości danych.
str.values <- paste(data, collapse="")
# "11100112220002110102"
to wali w dół dane w jeden długi ciąg, dzięki czemu możemy użyć wyrażenia regularnego na nim.
Krok 2: Zastosuj wyrażenie regularne, aby znaleźć lokalizacje i długości wszystkich dopasowań w ciągu znaków.
str.matches <- gregexpr("1[0]{1,3}1", str.values)
# [[1]]
# [1] 3 16
# attr(,"match.length")
# [1] 4 3
# attr(,"useBytes")
# [1] TRUE
W tym przypadku używamy wyrażenia regularnego szukać pierwszego wzoru, od jednego do trzech zer ([0]{2,}
) z nich po obu stronach (1[0]{1,3}1
). Będziemy musieli dopasować cały wzór, aby zapobiec konieczności sprawdzania pasujących lub dwójek na końcach. Odejmiemy te końce w następnym kroku.
Krok 3: Napisz je we wszystkich zgodnych lokalizacjach w oryginalnym wektorze.
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
Robimy tu kilka kroków naraz. Najpierw tworzymy listę sekwencji liczb z liczb pasujących do wyrażenia regularnego. W tym przypadku są dwa dopasowania, które rozpoczynają się od indeksów 3 i 16 i mają odpowiednio długość 4 i 3 elementy. Oznacza to, że nasze zera znajdują się w indeksach (3 + 1) :(3-2 + 4) lub 4: 5 i przy (16 + 1) :(16-2 + 3) lub 17:17. Łączymy ("wklejamy") te sekwencje, ponownie korzystając z opcji "zwiń", na wypadek gdyby było kilka dopasowań. Następnie używamy drugiej konkatenacji, aby umieścić sekwencje wewnątrz funkcji kombajnu (c()
). Korzystając z funkcji "eval" i "parsuj", przekształcamy ten tekst w kod i przekazujemy go jako wartości indeksu do tablicy [data]. Piszemy wszystkie w tych lokalizacjach.
Krok x: Powtórz dla każdego wzoru. W takim przypadku musimy wykonać drugie wyszukiwanie i odszukać od jednego do trzech zer po dwóch stronach po obu stronach, a następnie uruchomić to samo zdanie, co w kroku 3, ale przydzielając dwa, zamiast jednego.
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
Aktualizacja: ja sobie sprawę, że oryginalny problem powiedział, aby dopasować jeden do trzech zer w rzędzie, raczej niż „dwa lub więcej”, który napisałem do oryginalnego kodu. Zaktualizowałem wyrażenia regularne i wyjaśnienia, chociaż kod pozostaje ten sam.
Tak więc, faktycznie poszłam na tę w końcu, uwielbiałam możliwość kontrolowania wzorów - ale doceniam wszystkie sugestie. Będę jednak pamiętać o tych różnych metodach w różnych okolicznościach. Naprawdę to doceniam. –