will - grep usando un vector de caracteres con mĂșltiples patrones
grep two strings in r (9)
Estoy tratando de usar grep
para probar si un vector de cadenas está presente en otro vector o no, y para generar los valores que están presentes (los patrones coincidentes).
Tengo un marco de datos como este:
FirstName Letter
Alex A1
Alex A6
Alex A7
Bob A1
Chris A9
Chris A6
Tengo un vector de patrones de cadenas que se encuentran en las columnas "Carta", por ejemplo: c("A1", "A9", "A6")
.
Me gustaría comprobar si alguna de las cadenas en el vector de patrones está presente en la columna "Carta". Si lo son, me gustaría el resultado de valores únicos.
El problema es que no sé cómo usar grep
con múltiples patrones. Lo intenté:
matches <- unique (
grep("A1| A9 | A6", myfile$Letter, value=TRUE, fixed=TRUE)
)
Pero me da 0 coincidencias que no es cierto, ¿alguna sugerencia?
¿Has probado las funciones match()
o charmatch()
?
Ejemplo de uso:
match(c("A1", "A9", "A6"), myfile$Letter)
Además del comentario de @ Marek sobre no incluir fixed==TRUE
, tampoco es necesario que tenga los espacios en su expresión regular. Debería ser "A1|A9|A6"
.
También mencionas que hay muchos patrones. Suponiendo que están en un vector
toMatch <- c("A1", "A9", "A6")
Luego puedes crear tu expresión regular directamente a partir de esto.
matches <- unique (grep(paste(toMatch,collapse="|"),
myfile$Letter, value=TRUE))
Basado en la publicación de Brian Digg, aquí hay dos funciones útiles para filtrar listas:
#Returns all items in a list that are not contained in toMatch
#toMatch can be a single item or a list of items
exclude <- function (theList, toMatch){
return(setdiff(theList,include(theList,toMatch)))
}
#Returns all items in a list that ARE contained in toMatch
#toMatch can be a single item or a list of items
include <- function (theList, toMatch){
matches <- unique (grep(paste(toMatch,collapse="|"),
theList, value=TRUE))
return(matches)
}
Buenas respuestas, sin embargo, no olvide el filter()
de dplyr:
patterns <- c("A1", "A9", "A6")
>your_df
FirstName Letter
1 Alex A1
2 Alex A6
3 Alex A7
4 Bob A1
5 Chris A9
6 Chris A6
result <- filter(your_df, grepl(paste(patterns, collapse="|"), Letter))
>result
FirstName Letter
1 Alex A1
2 Alex A6
3 Bob A1
4 Chris A9
5 Chris A6
No estoy seguro de si esta respuesta ya apareció ...
Para el patrón particular en la pregunta, puede hacerlo con una sola llamada grep()
,
grep("A[169]", myfile$Letter)
Para agregar a la respuesta de Brian Diggs.
Otra forma de usar grepl devolverá un marco de datos que contiene todos sus valores.
toMatch <- myfile$Letter
matches <- myfile[grepl(paste(toMatch, collapse="|"), myfile$Letter), ]
matches
Letter Firstname
1 A1 Alex
2 A6 Alex
4 A1 Bob
5 A9 Chris
6 A6 Chris
Tal vez un poco más limpio ... tal vez?
Sugiero escribir un pequeño guión y hacer búsquedas múltiples con Grep. Nunca he encontrado una manera de buscar patrones múltiples, y créanme, ¡lo he buscado!
Al igual que su archivo de shell, con una cadena incrustada:
#!/bin/bash
grep *A6* "Alex A1 Alex A6 Alex A7 Bob A1 Chris A9 Chris A6";
grep *A7* "Alex A1 Alex A6 Alex A7 Bob A1 Chris A9 Chris A6";
grep *A8* "Alex A1 Alex A6 Alex A7 Bob A1 Chris A9 Chris A6";
Luego ejecute escribiendo myshell.sh.
Si desea poder pasar la cadena en la línea de comando, hágalo así, con un argumento de shell; esto es notación bash por cierto:
#!/bin/bash
$stingtomatch = "${1}";
grep *A6* "${stingtomatch}";
grep *A7* "${stingtomatch}";
grep *A8* "${stingtomatch}";
Etcétera.
Si hay muchos patrones para combinar, puede ponerlo en un ciclo for.
Usando el sapply
patterns <- c("A1", "A9", "A6")
df <- data.frame(name=c("A","Ale","Al","lex","x"),Letters=c("A1","A2","A9","A1","A9"))
name Letters
1 A A1
2 Ale A2
3 Al A9
4 lex A1
5 x A9
df[unlist(sapply(patterns, grep, df$Letters, USE.NAMES = F)), ]
name Letters
1 A A1
4 lex A1
3 Al A9
5 x A9
quita los espacios. Entonces hazlo
coincide con <- unique (grep ("A1 | A9 | A6", myfile $ Letter, value = TRUE, fixed = TRUE))