compare strings, se o registro do dataframe corresponder uma vez, continue na próxima linha

Dec 04 2020

Eu tenho um dataframe assim:

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

Eu tenho uma lista assim:

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

Eu quero combinar strings no brand_listcom as strings na item_descripcoluna e remover as correspondências na item_descripcoluna. Quero criar outra coluna unbrandedque contém as strings limpas de item_descrip.

Meu problema é que tenho um muito grande brand_liste algumas das cadeias de caracteres desta lista estão combinando várias vezes na item_descripcoluna. Minha saída desejada é se uma correspondência já for encontrada para uma linha, então pule essa linha.

Saída desejada:

|    | 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 é o código que funciona para remover correspondências, mas remove todas as correspondências na item_descripcoluna. Por exemplo, no meu brand_listtenho ebce beerna lista. Para o primeiro registro, eu só quero ebcser removido e não beerporque uma combinação já foi feita. Se uma correspondência for feita na primeira parte da string, não processe mais esse registro e vá para a próxima.

Então, basicamente, parece que uma instrução if pode entrar na compreensão da lista, mas não tenho certeza de como escrever algo que diga: se correspondido, passe, caso contrário, continue procurando.

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

Eu tirei o máximo proveito desta linha aqui: https://stackoverflow.com/questions/51666374/how-to-remove-strings-present-in-a-list-from-a-column-in-pandas

Respostas

1 DaniMesejo Dec 04 2020 at 23:10

AVISO DE RESPONSABILIDADE: Sou o autor de trrex

Se você se preocupa com o desempenho, use 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)

Resultado

                 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

A função make construirá um regex trie . Para entender melhor o que está acontecendo, make gera a seguinte expressão regular:

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

O argumento n = 1, significa que o padrão será substituído apenas uma vez, a partir da documentação :

n int, padrão -1 (todos)

Number of replacements to make from start.