comparar cadenas, si el registro del marco de datos coincide una vez, continúe en la siguiente fila

Dec 04 2020

Tengo un marco de datos como este:

df = pd.DataFrame({'item_descrip': ['ebc root beer single', 
                                    'yic yac big pack freshmint', 
                                    'froggy jumbo flakes',
                                    'jumbo tart warmer',
                                    'beer jerky'
                                   ]
})

Tengo una lista como esta:

brand_list = ['ebc', 'yic yac', 'beer', 'jumbo', 'tart', 'froggy']

Quiero hacer coincidir cadenas en el brand_listcon las cadenas en la item_descripcolumna y eliminar las coincidencias en la item_descripcolumna. Quiero crear otra columna unbrandedque contenga las cadenas limpiadas de item_descrip.

Mi problema es que tengo una muy grande brand_listy algunas de las cadenas de esta lista coinciden varias veces en la item_descripcolumna. Mi resultado deseado es que si ya se encuentra una coincidencia para una fila, omita esa fila.

Salida deseada:

|    | item_descrip                       | unbranded                          |
|---:|:-----------------------------------|:-----------------------------------|
|  0 | ebc root beer single               | root beer single                   |
|  1 | yic yac big pack freshmint singles | big pack freshmint singles         |
|  2 | froggy jumbo flakes                | jumbo flakes                       |
|  3 | jumbo tart warmer                  | tart warmer                        |
|  4 | beer jerky                         | jerky                              |

Este es el código que funciona para eliminar coincidencias, pero elimina todas las coincidencias en la item_descripcolumna. Por ejemplo, en mi brand_listtengo ebcy beeren la lista. Para el primer registro, solo quiero ebcque me eliminen y no beerporque ya se hizo una coincidencia. Si se hace una coincidencia en la primera parte de la cadena, no procese más ese registro y pase a la siguiente.

Entonces, básicamente, parece que una declaración if podría entrar en la comprensión de la lista, pero no estoy seguro de cómo escribir algo que diga: si coincide, sigue buscando.

df['unbranded'] = [' '.join([y for y in x.split() if not y.startswith(tuple(brand_list))]) for x in df['item_descrip']] 

Aproveché al máximo este resumen aquí: https://stackoverflow.com/questions/51666374/how-to-remove-strings-present-in-a-list-from-a-column-in-pandas

Respuestas

1 DaniMesejo Dec 04 2020 at 23:10

DESCARGO DE RESPONSABILIDAD: Soy el autor de trrex

Si le importa el rendimiento, utilice trrex :

import pandas as pd
import trrex as tx

df = pd.DataFrame({'item_descrip': ['ebc root beer single',
                                    'yic yac big pack freshmint',
                                    'froggy jumbo flakes',
                                    'jumbo tart warmer',
                                    'beer jerky'
                                    ]
                   })

brand_list = ['ebc', 'yic yac', 'beer', 'jumbo', 'tart', 'froggy']

df['unbranded'] = df['item_descrip'].str.replace(tx.make(brand_list), '', n=1)
print(df)

Salida

                 item_descrip            unbranded
0        ebc root beer single     root beer single
1  yic yac big pack freshmint   big pack freshmint
2         froggy jumbo flakes         jumbo flakes
3           jumbo tart warmer          tart warmer
4                  beer jerky                jerky

La función make construirá una expresión regular trie . Para comprender mejor lo que está sucediendo, make genera la siguiente expresión regular:

\b(?:froggy|tart|beer|yic yac|jumbo|ebc)\b

El argumento n = 1, significa que el patrón será reemplazado solo una vez, de la documentación :

n int, predeterminado -1 (todos)

Number of replacements to make from start.