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.


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)

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"

26

Vielleicht kann dies nützlich sein:

iconv('áéóÁÉÓçã', to="ASCII//TRANSLIT")
[1] "aeoAEOca"

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"

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"


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) 
}

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)

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"

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)]

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.


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))

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.