Una manera más elegante de eliminar nombres duplicados (frases) en los elementos de una cadena de caracteres.
Tienes un vector de nombres de organizaciones en un dataframe. Algunos están bien, otros tienen el nombre repetido dos veces en el mismo elemento. Además, cuando se repite el nombre, no hay espacio separador, por lo que el nombre tiene apariencia de camelCase.
Por ejemplo (se agregó la columna id para referencia general del dataframe):
id org
1 Alpha Company
2 Bravo InstituteBravo Institute
3 Charlie Group
4 Delta IncorporatedDelta Incorporated
pero debería verse así:
id org
1 Alpha Company
2 Bravo Institute
3 Charlie Group
4 Delta Incorporated
Tengo una solución que obtiene el resultado que necesito, código de ejemplo reproducible a continuación. Sin embargo, parece un poco largo y no muy elegante.
¿Alguien tiene un enfoque mejor para los mismos resultados?
Pregunta adicional: Si las organizaciones tienen “tipos” incluidos, como Alpha Company, LLC, entonces mi línea de gsub() para corregir el camelCase no funciona tan bien. ¿Alguna sugerencia sobre cómo ajustar la corrección de camelCase para tener en cuenta “, LLC” y seguir funcionando con el resto de la solución?
¡Gracias de antemano!
(Gracias al OP y a quienes ayudaron en la publicación anterior de SO sobre la división de cadenas de camelCase en R)
Paquetes
library(stringr)
Datos de juguete
df <- data.frame(id=1:4, org=c("Alpha Company", "Bravo InstituteBravo Institute", "Charlie Group", "Delta IncorporatedDelta Incorporated"))
Dividir y limpiar palabras camelCase
df$org_fix <- gsub("([A-Z])", " \\1", df$org)
df$org_fix <- str_trim(str_squish(df$org_fix))
Vector temporal con la mitad de los nombres de las organizaciones
df$org_half <- word(df$org_fix, start=1, end=(sapply(strsplit(df$org_fix, " "), length)/2)) # stringr::word
Duplicar el vector temporal
df$org_dbl <- paste(df$org_half, df$org_half)
Marcar VERDADERO para las organizaciones que contengan duplicados en el nombre
df$org_dup <- df$org_fix == df$org_dbl
Corregir los nombres de las organizaciones
df$org_fix <- ifelse(df$org_dup, df$org_half, df$org_fix)
Eliminar columnas excesivas
df <- df[,c("id", "org_fix")]
Datos de juguete para la pregunta adicional
df2 <- data.frame(id=1:4, org=c("Alpha Company, LLC", "Bravo InstituteBravo Institute", "Charlie Group", "Delta IncorporatedDelta Incorporated"))
davy.ai
Solución
Aquí hay una posible solución utilizando expresiones regulares:
“`{r}
library(stringr)
datos de prueba
df <- data.frame(id=1:4, org=c(“Alpha Company”, “Bravo InstituteBravo Institute”,
“Charlie Group”, “Delta IncorporatedDelta Incorporated”))
solucionar CamelCase y duplicados
df$org_fix <- str_replace_all(df$org, “(?<=[a-z])(?=[A-Z])|(?<=.)(?<=[A-Z])(?=[A-Z][a-z])”, ” “)
df$org_fix[df$org_fix == str_extract_all(df$org, “(?<=[a-z])(?=[A-Z])”)] <-
str_remove_all(df$org[df$org_fix == str_extract_all(df$org, “(?<=[a-z])(?=[A-Z])”)],
“(?<=[a-z])(?=[A-Z])”)
datos de prueba para la pregunta extra
df2 <- data.frame(id=1:4, org=c(“Alpha Company, LLC”, “Bravo InstituteBravo Institute”,
“Charlie Group”, “Delta IncorporatedDelta Incorporated”))
solucionar CamelCase y duplicados para df2
df2$org_fix <- str_replace_all(df2$org, “(?<=[a-z])(?=[A-Z])|(?<=.)(?<=[A-Z])(?=[A-Z][a-z])”, ” “)
df2$org_fix[df2$org_fix == str_extract_all(df2$org, “(?<=[a-z])(?=[A-Z])”)] <-
str_remove_all(df2$org[df2$org_fix == str_extract_all(df2$org, “(?<=[a-z])(?=[A-Z])”)],
“(?<=[a-z])(?=[A-Z])|, LLC”)
Luego, usamos
str_extract_all()
y==
para identificar qué filas tienen duplicados. Coincidimos con cualquier par de palabras consecutivas, con espacio en blanco opcional, que aparezcan dos veces:“`{r}
str_extract_all(df$org_fix, “\b(\w+)(\s*\b\1)+\b”)
Para la pregunta extra, solo necesitamos cambiar la expresión regular utilizada en
str_remove_all()
, para que también coincida con el sufijo, LLC
:{r}
str_remove_all(df2$org[df2$org_fix == str_extract_all(df2$org_fix, "\\b(\\w+)(\\s*\\b\\1)+\\b")],
"(?<=[a-z])(?=[A-Z])|, LLC")