comparer des chaînes, si l'enregistrement de la trame de données correspond une fois, puis passez à la ligne suivante

Dec 04 2020

J'ai un dataframe comme ceci:

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

J'ai une liste comme celle-ci:

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

Je veux faire correspondre les chaînes de la brand_listavec les chaînes de la item_descripcolonne et supprimer les correspondances dans la item_descripcolonne. Je souhaite créer une autre colonne unbrandedcontenant les chaînes nettoyées de item_descrip.

Mon problème est que j'ai un très grand brand_listet que certaines des chaînes de cette liste correspondent plusieurs fois dans la item_descripcolonne. Ma sortie souhaitée est si une correspondance est déjà trouvée pour une ligne, sautez cette ligne.

Sortie désirée:

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

C'est le code qui fonctionne pour supprimer les correspondances, mais il supprime toutes les correspondances dans la item_descripcolonne. Par exemple, dans mon brand_listj'ai ebcet beerdans la liste. Pour le premier enregistrement, je veux seulement ebcêtre supprimé et non beerdepuis qu'un match a déjà été fait. Si une correspondance est faite sur la première partie de la chaîne, ne traitez plus cet enregistrement et passez à la suivante.

Donc, fondamentalement, il semble qu'une instruction if puisse entrer dans la compréhension de la liste, mais je ne suis pas sûr de savoir comment écrire quelque chose qui dit: si la correspondance est acceptée, sinon continuez à chercher.

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

J'ai tiré le meilleur parti de ce one-liner ici: https://stackoverflow.com/questions/51666374/how-to-remove-strings-present-in-a-list-from-a-column-in-pandas

Réponses

1 DaniMesejo Dec 04 2020 at 23:10

AVERTISSEMENT: je suis l'auteur de trrex

Si vous vous souciez des performances, utilisez 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)

Production

                 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 fonction make construira un trie regex . Pour mieux comprendre ce qui se passe, make génère l'expression régulière suivante:

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

L'argument n = 1, signifie que le motif ne sera remplacé qu'une seule fois, d'après la documentation :

n int, par défaut -1 (tous)

Number of replacements to make from start.