Ersetzen Sie mehrere Buchstaben durch Akzente durch gsub

68

Natürlich könnte ich bestimmte Argumente wie dieses ersetzen:

    mydata=c("á","é","ó")
    mydata=gsub("á","a",mydata)
    mydata=gsub("é","e",mydata)
    mydata=gsub("ó","o",mydata)
    mydata

Aber es gibt sicherlich einen einfacheren Weg, dies alles in einer einzigen Linie zu tun, oder? Ich finde die gsub-Hilfe nicht sehr umfassend.

Joschi
quelle
Wenn Sie verschiedene Muster durch dasselbe lapplyersetzen möchten , sollte dies möglich sein , aber da Sie verschiedene Muster durch unterschiedliche Zeichenfolgen ersetzen möchten, müssen Sie diese auf die eine oder andere Weise noch angeben ...
juba
2
Möglicherweise können chartrSie dies verwenden.
Andrie
30
Die gsubfnFunktion im gsubfnPaket ist eine Verallgemeinerung gsub, die dies in einem Aufruf tun kann: gsubfn(".", list("á"="a", "é"="e", "ó"="o"), c("á","é","ó"))
G. Grothendieck
@ G.Grothendieck. Das ist großartig und funktioniert auch für alle Arten von Charakteren. Sehr wertvoller Kommentar. Vielen Dank!
Joschi
1
Für Leute, die nach einer allgemeineren Lösung für diese Frage suchen, ist hier eine hilfreichere Antwort: stackoverflow.com/a/7664655/1036500
Ben

Antworten:

83

Verwenden Sie die Zeichenübersetzungsfunktion

chartr("áéó", "aeo", mydata)
kith
quelle
Das ist cool für Charaktere ... Aber funktioniert das auch mit speziellen Zeichen wie Unterstrichen, Punkten usw. Es ist nicht in Frage, wäre trotzdem interessant, auch für diesen Fall etwas zu wissen ...
Joschi
@ Joschi, deine Frage spricht nicht darüber. Ich denke, Sie müssen ihnen entkommen, weil sie Sonderzeichen sind ...
Arun
33

Eine interessante Frage! Ich denke, die einfachste Möglichkeit besteht darin, eine spezielle Funktion zu entwickeln, so etwas wie ein "multi" gsub ():

mgsub <- function(pattern, replacement, x, ...) {
  if (length(pattern)!=length(replacement)) {
    stop("pattern and replacement do not have the same length.")
  }
  result <- x
  for (i in 1:length(pattern)) {
    result <- gsub(pattern[i], replacement[i], result, ...)
  }
  result
}

Welches gibt mir:

> mydata <- c("á","é","ó")
> mgsub(c("á","é","ó"), c("a","e","o"), mydata)
[1] "a" "e" "o"
Theodore Lytras
quelle
26

Vielleicht kann dies nützlich sein:

iconv('áéóÁÉÓçã', to="ASCII//TRANSLIT")
[1] "aeoAEOca"
Rcoster
quelle
Bei der aktuellsten Version von R, die ich verwende, wird der Anruf iconv('áéóÁÉÓçã', to="ASCII//TRANSLIT")zurückgegeben "'a'e'o'A'E'Oc~a". Hat sich das Verhalten in den R-Versionen geändert oder hat dies mit meiner Standardcodierung zu tun?
Aaron
@ Aaron: Ich weiß nicht, ob es sich um ein Codierungsproblem handelt. Ich habe es hier bei R 3.3.1 versucht und wie erwartet gearbeitet.
Rcoster
11

Sie können das stringiPaket verwenden, um diese Zeichen zu ersetzen.

> stri_trans_general(c("á","é","ó"), "latin-ascii")

[1] "a" "e" "o"
Maciej
quelle
9

Dies ist @kith sehr ähnlich, jedoch in Funktionsform und mit den häufigsten diakritischen Fällen:

removeDiscritics <- function(string) {
  chartr(
     "ŠŽšžŸÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðñòóôõöùúûüýÿ"
    ,"SZszYAAAAAACEEEEIIIIDNOOOOOUUUUYaaaaaaceeeeiiiidnooooouuuuyy"
    , string
  )
}


removeDiscritics("test áéíóú")

"test aeiou"

Murta
quelle
einfach und großartig
HAVB
7

Eine andere mgsubImplementierung mitReduce

mystring = 'This is good'
myrepl = list(c('o', 'a'), c('i', 'n'))

mgsub2 <- function(myrepl, mystring){
  gsub2 <- function(l, x){
   do.call('gsub', list(x = x, pattern = l[1], replacement = l[2]))
  }
  Reduce(gsub2, myrepl, init = mystring, right = T) 
}
Ramnath
quelle
7

Ein Problem bei einigen der oben genannten Implementierungen (z. B. bei Theodore Lytras) besteht darin, dass die Muster, wenn sie aus mehreren Zeichen bestehen, in Konflikt geraten können, wenn ein Muster ein Teilstring eines anderen ist. Eine Möglichkeit, dies zu lösen, besteht darin, eine Kopie des Objekts zu erstellen und die Musterersetzung in dieser Kopie durchzuführen. Dies ist in meinem Paket bayesbio implementiert, das auf CRAN verfügbar ist.

mgsub <- function(pattern, replacement, x, ...) {
  n = length(pattern)
  if (n != length(replacement)) {
    stop("pattern and replacement do not have the same length.")
  }
  result = x
  for (i in 1:n) {
    result[grep(pattern[i], x, ...)] = replacement[i]
  }
  return(result)
}

Hier ist ein Testfall:

  asdf = c(4, 0, 1, 1, 3, 0, 2, 0, 1, 1)

  res = mgsub(c("0", "1", "2"), c("10", "11", "12"), asdf)
Andy McKenzie
quelle
3

Nicht so elegant, aber es funktioniert und macht was Sie wollen

> diag(sapply(1:length(mydata), function(i, x, y) {
+   gsub(x[i],y[i], x=x)
+ }, x=mydata, y=c('a', 'b', 'c')))
[1] "a" "b" "c"
Jilber Urbina
quelle
1

Sie können die matchFunktion verwenden. Hier wird match(x, y)der Index zurückgegeben, an ydem das Element von xübereinstimmt. Dann können Sie die zurückgegebenen Indizes verwenden, um einen anderen Vektor (z. B. z) zu unterteilen, der die Ersetzungen für die Werte von enthält x, die entsprechend mit übereinstimmen y. In Ihrem Fall:

mydata <- c("á","é","ó")
desired <- c('a', 'e', 'o')

desired[match(mydata, mydata)]

In einem einfacheren Beispiel betrachten wir die Situation unten, wo ich zu ersetzen versuchte , afür 'alpha', 'b'für 'beta'und so weiter.

x <- c('a', 'a', 'b', 'c', 'b', 'c', 'e', 'e', 'd')

y <- c('a', 'b', 'c', 'd', 'e')
z <- c('alpha', 'beta', 'gamma', 'delta', 'epsilon')

z[match(x, y)]
justin1.618
quelle
1

Bezogen auf Justins Antwort:

> m <- c("á"="a", "é"="e", "ó"="o")
> m[mydata]
  á   é   ó 
"a" "e" "o" 

Und Sie können die Namen mit loswerden, names(*) <- NULLwenn Sie wollen.

Dthal
quelle
0

In diesem Fall hat das nicht so viel Sinn, aber wenn es nur zwei sind, können Sie sie auch mit gsub kombinieren:

mydata <- gsub("á","a", gsub("é","e",mydata))

Maria
quelle