porównaj ciągi, jeśli rekord dataframe pasuje raz, a następnie przejdź do następnego wiersza

Dec 04 2020

Mam taką ramkę danych:

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

Mam taką listę:

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

Chcę dopasować ciągi w kolumnie brand_listdo ciągów w item_descripkolumnie i usunąć dopasowania w item_descripkolumnie. Chcę utworzyć kolejną kolumnę unbrandedzawierającą wyczyszczone ciągi z item_descrip.

Mój problem polega na tym, że mam bardzo duży brand_listi niektóre ciągi z tej listy pasują wielokrotnie w item_descripkolumnie. Mój pożądany wynik jest taki, że jeśli dopasowanie zostało już znalezione dla jednego wiersza, pomiń ten wiersz.

Pożądane wyjście:

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

To jest kod, który działa w celu usunięcia dopasowań, ale usuwa wszystkie dopasowania w item_descripkolumnie. Na przykład w moim brand_listmam ebci beerna liście. Po pierwsze, chcę tylko ebczostać usunięty, a nie, beerponieważ dopasowanie zostało już wykonane. Jeśli dopasowanie zostanie wykonane na pierwszej części ciągu, nie przetwarzaj tego rekordu dalej i przejdź do następnego.

Zasadniczo wydaje się, że instrukcja if mogłaby przejść do rozumienia listy, ale nie jestem pewien, jak napisać coś, co mówi: jeśli pasujące hasło, w przeciwnym razie szukaj dalej.

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

Mam tutaj większość tego jednokładkowego: https://stackoverflow.com/questions/51666374/how-to-remove-strings-present-in-a-list-from-a-column-in-pandas

Odpowiedzi

1 DaniMesejo Dec 04 2020 at 23:10

ZRZECZENIE SIĘ: Jestem autorem trrex

Jeśli zależy Ci na wydajności, użyj 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)

Wynik

                 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

Funkcja make zbuduje wyrażenie regularne trie . Aby lepiej zrozumieć, co się dzieje, make generuje następujące wyrażenie regularne:

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

Argument n = 1 oznacza, że ​​wzorzec zostanie podmieniony tylko raz, z dokumentacji :

n int, domyślnie -1 (wszystkie)

Number of replacements to make from start.