2012-05-22 21 views
6

Quiero reemplazar caracteres no ASCII (por ahora, solo español), por su equivalente ASCII. Si tengo "á", quiero reemplazarlo por "a" y así sucesivamente.Reemplazar caracteres no ASCII con una lista de cadenas definida sin un bucle en R

Construí esta función (funciona bien), pero no quiero usar un bucle (incluyendo bucles internos como sapply).

latin2ascii<-function(x) { 
if(!is.character(x)) stop ("input must be a character object") 
require(stringr) 
mapL<-c("á","é","í","ó","ú","Á","É","Í","Ó","Ú","ñ","Ñ","ü","Ü") 
mapA<-c("a","e","i","o","u","A","E","I","O","U","n","N","u","U") 
for(y in 1:length(mapL)) { 
    x<-str_replace_all(x,mapL[y],mapA[y]) 
    } 
x 
} 

¿Hay una forma elegante de resolverlo? Cualquier ayuda, sugerencia o modificación se aprecia

Respuesta

7

gsubfn() en el paquete del mismo nombre es muy agradable para este tipo de cosas:

library(gsubfn) 

# Create a named list, in which: 
# - the names are the strings to be looked up 
# - the values are the replacement strings 
mapL <- c("á","é","í","ó","ú","Á","É","Í","Ó","Ú","ñ","Ñ","ü","Ü") 
mapA <- c("a","e","i","o","u","A","E","I","O","U","n","N","u","U") 

# ll <- setNames(as.list(mapA), mapL) # An alternative to the 2 lines below 
ll <- as.list(mapA) 
names(ll) <- mapL 


# Try it out 
string <- "ÍÓáÚ" 
gsubfn("[áéíóúÁÉÍÓÚñÑüÜ]", ll, string) 
# [1] "IOaU" 

Editar:

G. Grothendieck señala que la base R también tiene una función para esto:

A <- paste(mapA, collapse="") 
L <- paste(mapL, collapse="") 
chartr(L, A, "ÍÓáÚ") 
# [1] "IOaU" 
+0

Gracias! funciona perfectamente. Solo una pregunta (solo para saber); ¿sabes si la función gsubfn utiliza algún tipo de bucle interno? ¿Debería ser más rápido que sapply? –

+0

@ Álvaro - No creo que 'gsubfn()' sea particularmente rápido, 'simplemente' conveniente y elegante. –

+1

También vea 'chartr' en la base de R que parece estar bien para el problema tal como se indicó, aunque si hay variaciones en el problema real como reemplazar dos secuencias de caracteres,' gsubfn' podría manejarlo pero no 'chartr'. –

2

Me gusta la versión de Josh, pero pensé que podría agregar un Otra solución 'vectorizada'. Devuelve un vector de cadenas sin acentos. También solo se basa en las funciones base.

x=c('íÁuÚ','uíÚÁ') 

mapL<-c("á","é","í","ó","ú","Á","É","Í","Ó","Ú","ñ","Ñ","ü","Ü") 
mapA<-c("a","e","i","o","u","A","E","I","O","U","n","N","u","U") 
split=strsplit(x,split='') 
m=lapply(split,match,mapL) 
mapply(function(split,m) paste(ifelse(is.na(m),split,mapA[m]),collapse='') , split, m) 
# "iAuU" "uiUA" 
Cuestiones relacionadas