es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

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"))
Tags:  , , , ,

Answer

  1. Avatar for 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”)



    Explicación: Primero utilizamos `str_replace_all()` para agregar un espacio entre las palabras de camelCase en la columna `org`. Utilizamos una expresión regular para emparejar la posición entre una letra minúscula seguida de una letra mayúscula, o entre dos letras mayúsculas consecutivas seguidas de una letra minúscula: ```{r} str_replace_all(df$org, "(?<=[a-z])(?=[A-Z])|(?<=.)(?<=[A-Z])(?=[A-Z][a-z])", " ")

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


    Finalmente, usamos `str_remove_all()` para eliminar duplicados consecutivos de la columna `org` para aquellas filas donde encontramos duplicados: ```{r} str_remove_all(df$org[df$org_fix == str_extract_all(df$org_fix, "\\b(\\w+)(\\s*\\b\\1)+\\b")], "(?<=[a-z])(?=[A-Z])")

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

Comments are closed.