2017-07-25 6 views
3

Sagen wir, ich habe zwei Vektoren wie so:Ersetzen String in R mit Mustern und Ersatz beide Vektoren

a <- c("this", "is", "test") 
b <- c("that", "was", "boy") 

ich auch eine String-Variable wie so haben:

string <- "this is a story about a test" 

Ich möchte Werte ersetzen in String so dass es die folgenden:

string <- "that was a story about a boy" 

ich diese for-Schleife ein tun könnte, aber ich will diese v sein ectorized. Wie soll ich das machen?

Antwort

8

Wenn Sie ein Nicht-Basispaket mit offener sind, wird stringi arbeiten wirklich gut hier:

stringi::stri_replace_all_fixed(string, a, b, vectorize_all = FALSE) 
#[1] "that was a story about a boy" 

Beachten Sie, dass dies auch die gleiche Art und Weise für die Eingabe Strings der Länge arbeitet> 1.

auf der sicheren Seite zu sein, können Sie diese anpassen - ähnlich wie Ruser Antwort - für Wortgrenzen zu überprüfen, bevor ersetzt:

stri_replace_all_regex(string, paste0("\\b", a, "\\b"), b, vectorize_all = FALSE) 

Dies würde sicherstellen, dass Sie dies nicht tun Unfall ersetzen Sie zum Beispiel his durch hwas.

3
> library(stringi) 
> stri_replace_all_regex(string, "\\b" %s+% a %s+% "\\b", b, vectorize_all=FALSE) 
#[1] "that was a story about a boy" 
4

Hier sind einige Lösungen. Sie funktionieren auch dann, wenn string ein Zeichenvektor von Strings ist, in welchem ​​Fall Substitutionen für jede Komponente davon durchgeführt werden.

1) Reduzieren Dies verwendet keine Pakete.

Reduce(function(x, i) gsub(paste0("\\b", a[i], "\\b"), b[i], x), seq_along(a), string) 
## [1] "that was a story about a boy" 

2) gsubfngsubfn ist wie gsub aber der Ersatz Argument kann eine Liste von Ersetzungen (oder bestimmte andere Objekte sein).

library(gsubfn) 

gsubfn("\\w+", setNames(as.list(b), a), string) 
## [1] "that was a story about a boy" 

3) loop Dies ist nicht vektorisiert sondern zum Vergleich hinzugefügt. Keine Pakete werden verwendet.

out <- string 
for(i in seq_along(a)) out <- gsub(paste0("\\b", a[i], "\\b"), b[i], out) 
out 
## [1] "that was a story about a boy" 

Hinweis: Es gibt einige Frage, ob Zyklen möglich. wenn

Zum Beispiel
a <- c("a", "A") 
b <- rev(a) 

wollen wir

  • "a" mit "A" ersetzt werden und dann wieder auf "a" wieder, oder
  • "a" und "A" ausgetauscht werden.

Alle oben gezeigten Lösungen nehmen den ersten Fall an. Wenn wir den zweiten Fall wollten, dann führe die Operation zweimal durch.Wir werden zeigen, mit (2), weil es die kürzeste, aber die gleiche Idee gilt für sie alle:

# swap "a" and "A" 
a <- c("a", "A") 
b <- rev(a) 

tmp <- gsubfn("\\w+", setNames(as.list(seq_along(a)), a), string) 
gsubfn("\\w+", setNames(as.list(b), seq_along(a)), tmp) 
## [1] "this is A story about A test" 
+0

Nice! Ich war noch nicht Reduce ausgesetzt. Danke vielmals. – hjms

+0

Fügen Sie einen Hinweis zu den Zyklen hinzu –

+0

Auch 'regmatches (string, gregexpr (einfügen (a, collapse =" | "), string)) <- list (b)' funktioniert ähnlich wie 'gsubfn' – thelatemail

2

mit einer kleinen Funktion in und Chipping, die nur auf R base beruht:

repWords <- function(string,toRep,Rep,sep='\\s'){ 

    wrds <- unlist(strsplit(string,sep)) 
    ix <- match(toRep,wrds) 
    wrds[ix] <- Rep 
    return(paste0(wrds,collapse = ' ')) 

} 

a <- c("this", "is", "test") 
b <- c("that", "was", "boy") 

string <- "this is a story about a test" 

> repWords(string,a,b) 
[1] "that was a story about a boy" 

Hinweis :

Dies setzt voraus, dass Sie eine übereinstimmende Anzahl von Ersetzungen haben. Sie können das Trennzeichen mit sep definieren.

2

Apropos externe Pakete, hier ist ein anderes:

a <- c("this", "is", "test") 
b <- c("that", "was", "boy") 
x <- "this is a story about a test" 


library(qdap) 
mgsub(a,b,x) 

die gibt:

"that was a story about a boy" 
+0

netter! 'mgsub' kann das Leben ein bisschen leichter machen es scheint – Sotos

+0

Wenn' a <- "a"; b <- "A" 'dann verwandelt es" about "in" About ", was inkorrekt erscheint. –