2012-05-24 5 views
6

Si tengo una cadena y quiero dividir en el último dígito y mantener la última parte de la división hpw, ¿puedo hacer eso?dividir en la última aparición de dígitos, tomar la 2da parte

x <- c("ID", paste0("X", 1:10, state.name[1:10])) 

me gustaría

[1] NA   "Alabama"  "Alaska"  "Arizona"  "Arkansas" 
[6] "California" "Colorado" "Connecticut" "Delaware" "Florida"  
[11] "Georgia"  

Pero conformaría con:

[1] "ID"   "Alabama"  "Alaska"  "Arizona"  "Arkansas" 
[6] "California" "Colorado" "Connecticut" "Delaware" "Florida"  
[11] "Georgia"  

puedo conseguir la primera parte por:

unlist(strsplit(x, "[^0-9]*$")) 

Pero quiere que la segunda parte .

Gracias de antemano.

Respuesta

2
library(stringr) 
unlist(lapply(str_split(x, "[0-9]"), tail,n=1)) 

da

[1] "ID"   "Alabama"  "Alaska"  "Arizona"  "Arkansas" "California" "Colorado" "Connecticut" "Delaware" 
[10] "Florida"  "Georgia" 

Me gustaría ver la documentación para stringr (más posiblemente) un enfoque aún mejor.

+0

Ambas opciones excelentes que fueron los primeros. Gracias. –

+3

Puede hacer esencialmente lo mismo sin cargar stringr: 'sapply (strsplit (x," [0-9] "), tail, n = 1)' – Dason

+0

@Dason - esa es una solución ordenada y fácilmente comprensible. Siempre me olvido de usar 'tail' y' head' - tal vez debería escribir algo en mi archivo '.First' que diga' "No te olvides de las funciones x, y, z - Signed, Me." ' – thelatemail

2

Esto parece un poco torpe, pero funciona:

state.pt2 <- unlist(strsplit(x,"^.[0-9]+")) 
state.pt2[state.pt2!=""] 

que sería bueno para eliminar los "" 's generados por el partido en el inicio de la cadena, pero no puedo imaginar eso.

Aquí hay otro método que usa substr y gregexpr también que evita tener que subconjunto de los resultados:

substr(x,unlist(lapply(gregexpr("[0-9]",x),max))+1,nchar(x)) 
+0

Bien hecho y en base. Estoy muy agradecido. +1 –

+0

¡Qué amable eres! :-D – thelatemail

4

Usted puede hacer esto un paso más fácil con una expresión regular:

gsub("(^.*\\d+)(\\w*)", "\\2", x) 

Resultados en:

[1] "ID"   "Alabama"  "Alaska"  "Arizona"  "Arkansas" "California" "Colorado" "Connecticut" 
[9] "Delaware" "Florida"  "Georgia" 

¿Qué significa la expresión regular:

  1. "(^.*\\d+)(\\w*)": Busque dos grupos de caracteres.
    • El primer grupo (^.*\\d+) busca cualquier dígito seguido de al menos un número al comienzo de la cadena.
    • El segundo grupo \\w* busca un carácter alfanumérico.
  2. El "\\2" como segundo argumento a gsub() significa para reemplazar la cadena original con el segundo grupo que se encontró la expresión regular.
+0

Incluso demostré algo similar con la remodelación del nombre de los nombres de las columnas. Gracias por recordarme que soy un doof. Probablemente la respuesta más corta. Y una gran explicación, que falta en muchas respuestas de expresiones regulares. +1 –

2

gsubfn

Pruebe esta solución gsubfn:

> library(gsubfn) 
> strapply(x, ".*\\d(\\w*)|$", ~ if (nchar(z)) z else NA, simplify = TRUE) 
[1] NA   "Alabama"  "Alaska"  "Arizona"  "Arkansas" 
[6] "California" "Colorado" "Connecticut" "Delaware" "Florida"  
[11] "Georgia"  

Coincide con el último dígito seguido de caracteres de texto y devuelve la palabra caracteres o si eso no funciona coincide con el final de la línea (para asegurarse de que coincida con algo). Si la primera coincidencia tuvo éxito, devuélvela; de lo contrario, la referencia posterior estará vacía, así que devuelva NA.

Tenga en cuenta que la fórmula es una manera abreviada de escribir la función function(z) if (nchar(z)) z else NA y que la función podría reemplazar alternativamente la fórmula a expensas de un poco más de las teclas.

gsub

Una estrategia similar también podría trabajar utilizando sólo recta gsub pero requiere dos líneas y una expresión regular marginalmente más complejo. Aquí se utiliza la segunda alternativa a sorber los no partidos de la primera alternativa:

> s <- gsub(".*\\d(\\w*)|.*", "\\1", x) 
> ifelse(nchar(s), s, NA) 
[1] NA   "Alabama"  "Alaska"  "Arizona"  "Arkansas" 
[6] "California" "Colorado" "Connecticut" "Delaware" "Florida"  
[11] "Georgia"  

EDIT: pequeñas mejoras

+0

Gracias y por obtener la NA. Muy corto también +1 –

Cuestiones relacionadas