Распределение значений по группам
В примере ниже использованы условные данные. Мой рабочий датасет состоит из 250к позиций, а список продуктов из 3к позиций.
df = pd.DataFrame(['ap','apple','cтекло apple','a','ap','brother', 'br', 'brother 2'])
df.columns = ['nom']
product_list = ['ap','apple','br','brother', 'br s']
def categorize(row):
for i in product_list:
if i in row:
return i
df['product'] = df['nom'].apply(categorize)
print(df)
Проблема заключается в том, что позиция 'стекло apple' попадает в категорию 'ap' вместо 'apple'. Как решить эту проблему?
Ответы (2 шт):
Элементарно, Ватсон. Сортируем список продуктов по длине слова от длинных к коротким. Так, чтобы сначала искать более длинные слова, а потом уже более короткие. Это тоже не панацея, но в вашем случае поможет.
product_list = sorted(['ap','apple','br','brother', 'br s'], key=len, reverse=True)
# product_list = ['brother', 'apple', 'br s', 'ap', 'br']
На выходе:
nom product
0 ap ap
1 apple apple
2 cтекло apple apple
3 a None
4 ap ap
5 brother brother
6 br br
7 brother 2 brother
В дополнение к ответу @CrazyElf предложу иной способ сопоставления массивов - через regex. Можно (предварительно отсортировав, как указал @CrazyElf), а также экранировав возможные специальные символы, создать паттерн вида (слово1|слово2|слово3)
и затем применить к серии метод .str.extract
, который и вытащит совпадающие подстроки - так мы уходим от необходимости применять циклы в явном виде. В примере ниже паттерн сделан из 5000 позиций, отрабатывает нормально:
import re
import pandas as pd
df = pd.DataFrame(['ap', 'apple', 'cтекло apple', 'a', 'ap', 'brother', 'br', 'brother 2'], columns=['nom'])
product_list = '(' + '|'.join(map(re.escape, sorted(['ap', 'apple', 'br', 'brother', 'br s'] * 1000, key=len, reverse=True))) + ')'
df['product'] = df['nom'].str.extract(product_list)
print(df)
nom product
0 ap ap
1 apple apple
2 cтекло apple apple
3 a NaN
4 ap ap
5 brother brother
6 br br
7 brother 2 brother
Скорость не мерял.