Poiché sembra esserci molto interesse nella risposta a questa domanda, ho pensato di scrivere un metodo di espressioni regolari alternative per i posteri.
Utilizzando la funzione 'gregexpr', è possibile cercare i modelli e utilizzare le corrispondenze di posizione risultanti e le lunghezze di corrispondenza per richiamare i valori da modificare nel vettore originale. Il vantaggio di usare le espressioni regolari è che possiamo essere espliciti riguardo esattamente quali pattern vogliamo abbinare e, di conseguenza, non avremo casi di esclusione di cui preoccuparci.
Nota: il seguente esempio funziona come scritto, poiché assumiamo valori a una cifra. Potremmo facilmente adattarlo per altri pattern, ma possiamo prendere una piccola scorciatoia con caratteri singoli. Se volessimo farlo con possibili valori a più cifre, vorremmo aggiungere un carattere di separazione come parte della prima funzione di concatenazione ('incolla').
Il Codice
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
Fase 1: fare una singola stringa di tutti i valori dei dati.
str.values <- paste(data, collapse="")
# "11100112220002110102"
Questo riduce i dati in una stringa lunga, quindi è possibile utilizzare un'espressione regolare su di esso.
Passaggio 2: applicare un'espressione regolare per trovare le posizioni e le lunghezze di qualsiasi corrispondenza all'interno della stringa.
str.matches <- gregexpr("1[0]{1,3}1", str.values)
# [[1]]
# [1] 3 16
# attr(,"match.length")
# [1] 4 3
# attr(,"useBytes")
# [1] TRUE
In questo caso, stiamo usando un'espressione regolare per cercare il primo modello, da uno a tre zeri ([0]{2,}
) con quelli su entrambi i lati (1[0]{1,3}1
). Dovremo abbinare l'intero schema, al fine di evitare di dover verificare se vi sono abbinamenti o twos finali. Sottraggeremo quelle estremità nel passaggio successivo.
Passaggio 3: Scrivere quelli in tutte le posizioni corrispondenti nel vettore originale.
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
Stiamo facendo alcuni passaggi tutti insieme. Innanzitutto, stiamo creando un elenco di sequenze numeriche dai numeri che corrispondono all'espressione regolare. In questo caso, ci sono due partite, che iniziano agli indici 3 e 16 e sono lunghe 4 e 3 voci, rispettivamente. Ciò significa che i nostri zeri si trovano negli indici (3 + 1) :(3-2 + 4), o 4: 5 e in (16 + 1) :(16-2 + 3) o 17:17. Concateniamo ("incolla") queste sequenze usando di nuovo l'opzione "Collapse", nel caso ci siano più corrispondenze. Quindi, usiamo una seconda concatenazione per inserire le sequenze all'interno di una combinazione (c()
). Usando le funzioni 'eval' e 'parse', trasformiamo questo testo in codice e lo passiamo come valori di indice alla matrice [dati]. Scriviamo tutti quelli in quei luoghi.
Punto x: ripetere per ciascun motivo. In questo caso, dobbiamo eseguire una seconda ricerca e trovare da uno a tre zeri con due su ciascun lato e quindi eseguire la stessa istruzione del passaggio 3, ma assegnando due, anziché uno.
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
Aggiornamento: ho capito che il problema originale, ha detto per abbinare uno a tre zeri di fila, piuttosto che il "due o più" che ho scritto nel codice originale. Ho aggiornato le espressioni regolari e la spiegazione, anche se il codice rimane lo stesso.
quindi, alla fine ho optato per questo, mi è piaciuta la possibilità di avere il controllo sugli schemi, ma ho apprezzato tutti i suggerimenti. Terrò comunque nota di questi diversi metodi per diverse circostanze. Lo apprezzo davvero. –