Функция для замены списка числами и знаками в Python - PullRequest
0 голосов
/ 15 сентября 2018

У меня есть массив:

array(['Amazon', 'Amazon mix', 'Amazon, ICS', 'Beniano', 'Blend',
   'Blend-Forastero,Criollo', 'CCN51', 'Criollo', 'Criollo (Amarru)',
   'Criollo (Ocumare 61)', 'Criollo (Ocumare 67)',
   'Criollo (Ocumare 77)', 'Criollo (Ocumare)', 'Criollo (Porcelana)',
   'Criollo (Wild)', 'Criollo, +', 'Criollo, Forastero',
   'Criollo, Trinitario', 'EET', 'Forastero', 'Forastero (Amelonado)',
   'Forastero (Arriba)', 'Forastero (Arriba) ASS',
   'Forastero (Arriba) ASSS', 'Forastero (Catongo)',
   'Forastero (Nacional)', 'Forastero (Parazinho)',
   'Forastero(Arriba, CCN)', 'Forastero, Trinitario', 'Matina',
   'NA_bean', 'Nacional', 'Nacional (Arriba)', 'Other', 'Trinitario',
   'Trinitario (85% Criollo)', 'Trinitario (Amelonado)',
   'Trinitario (Scavina)', 'Trinitario, Criollo',
   'Trinitario, Forastero', 'Trinitario, Nacional',
   'Trinitario, TCGA'], dtype=object)

И я хочу стандартизировать их, чтобы удалить количество уникальных значений. Итак, я создал функцию:

def std_bean(text):
    replace = [
        ['\(',''],['\)',''],
        ['Amazon mix|Amazon, ICS|Blend-Forastero,Criollo|Criollo, Trinitario|Forastero, Trinitario|Trinitario 85% Criollo|Trinitario, Criollo|Trinitario, Forastero|Trinitario, Nacional','Blend'],
        ['Forastero Arriba|Forestero ASS|Forestero ASSS|Forastero Nacional|Forastero Catongo|Forastero Parazinho|Forastero Arriba ASS|ForasteroArriba, CCN|Forastero Arriba ASSS|Forastero Amelonado','Forastero'],
        ['Criollo Ocumare 77', 'Criollo'],
        ['Criollo Ocumare 61', 'Criollo'],
        ['Criollo Ocumare', 'Criollo'],
        ['Criollo Wild', 'Criollo'],
        ['Criollo, +', 'Criollo'],
        ['Criollo+', 'Criollo'],
        ['Criollo 67', 'Criollo'],
        ['Criollo, Forastero', 'Criollo'],
        ['Criollo Amarru', 'Criollo'],
        ['Forestero ASSS', 'Forastero'],
        ['Forastero ASS', 'Forastero'],
        ['Forestero', 'Forastero'],
        ['Trinitario Amelonado', 'Trinitario'],
        ['Forestero ASSS', 'Forastero'],
        ['Nacional Arriba', 'Nacional'],
        ['Trinitario, TCGA', 'Trinitario'],
        ['Criollo Porcelana','Criollo'],
        ['ForasteroS', 'Forastero']
    ]
    for i, j in replace:
        text = re.sub(i, j, text)
    return(text)
df['bean_type'].str.replace('.','').apply(std_bean).unique()

После применения у меня все еще есть такие значения, как «Criollo +», «CriolloForastero» и другие, которые я просто не могу заменить, я не знаю, как это исправить ...

array(['NA_bean', 'Criollo', 'Trinitario', 'Forastero', 'Blend', 'CCN51',
   'Nacional', 'Beniano', 'Criollo+', 'Amazon', 'EET',
   'Trinitario Scavina', 'CriolloForastero', 'Matina', 'Other'],
  dtype=object)

Может ли кто-нибудь помочь мне улучшить функцию? Я просто хочу объединить те, которые похожи друг на друга. Пометить как смешать тех, у кого есть более одного типа бобов (либо с запятой, либо с надписью mix, либо имя другого типа бобов внутри скобок) и оставить имя, которое не в скобках, для тех, кто не смеси.

Окончательный результат, который я хочу получить, - это только «Blend, Criollo, Forastero, NA_bean, Matina, Nacional и другие»

Я хочу сгруппировать их как смесь: 'Amazon mix | Amazon, ICS | Blend-Forastero, Criollo | Criollo, Trinitario | Forastero, Trinitario | Trinitario 85% Criollo | Тринитарио, Criollo | Тринитарио, Форастеро | Тринитарио, Насиональ'

Я хочу это как Форастеро: [Forastero Arriba | Forestero ASSS | Forestero ASSS | Forastero Nacional | Forastero Catongo | Forastero Parazinho | Forastero Arriba ASS | ForasteroArriba, CCN | Forastero Arriba ASSS | Forastero Amelonado ',' Forastero '] * 1016

и т. Д.

Ответы [ 2 ]

0 голосов
/ 15 сентября 2018

Добро пожаловать в StackOverflow. Похоже, нам нужно создать собственное правило, а не искать и заменять.

Найдите приведенный ниже код и проверьте, работает ли он для вас,

import pandas as pd

bean_type = {'bean_type': ['Amazon', 'Amazon mix', 'Amazon, ICS', 'Beniano', 'Blend',
                           'Blend-Forastero,Criollo', 'CCN51', 'Criollo', 'Criollo (Amarru)',
                           'Criollo (Ocumare 61)', 'Criollo (Ocumare 67)',
                           'Criollo (Ocumare 77)', 'Criollo (Ocumare)', 'Criollo (Porcelana)',
                           'Criollo (Wild)', 'Criollo, +', 'Criollo, Forastero',
                           'Criollo, Trinitario', 'EET', 'Forastero', 'Forastero (Amelonado)',
                           'Forastero (Arriba)', 'Forastero (Arriba) ASS',
                           'Forastero (Arriba) ASSS', 'Forastero (Catongo)',
                           'Forastero (Nacional)', 'Forastero (Parazinho)',
                           'Forastero(Arriba, CCN)', 'Forastero, Trinitario', 'Matina',
                           'NA_bean', 'Nacional', 'Nacional (Arriba)', 'Other', 'Trinitario',
                           'Trinitario (85% Criollo)', 'Trinitario (Amelonado)',
                           'Trinitario (Scavina)', 'Trinitario, Criollo',
                           'Trinitario, Forastero', 'Trinitario, Nacional',
                           'Trinitario, TCGA']}

df = pd.DataFrame(bean_type)


def blend_count(text):
    bean_types = ['criollo', 'trinitario', 'nacional', 'forastero']
    _blend_count = 0
    if 'blend' in text.lower():
        return 0
    for _bean_type in bean_types:
        if _bean_type in text.lower():
            _blend_count += 1
    return _blend_count


def blend_category(text):
    _blend_count = blend_count(text)
    _text = text.lower()
    if any(x in _text for x in ['blend', 'amazon']):
        return 'Blend'
    elif 'trinitario' in _text:
        if _blend_count == 1:
            return 'Trinitario'
        elif _blend_count > 1:
            return 'Blend'
    elif _text.startswith('forastero'):
        return 'Forastero'
    elif _text.startswith('nacional'):
        return 'Nacional'
    elif _text.startswith('criollo'):
        return 'Criollo'
    else:
        return text


df['blend_category'] = df['bean_type'].apply(blend_category)
# df['blend_count'] = df['bean_type'].apply(blend_count)

print(df)

Ниже мой вывод

                   bean_type blend_category
0                     Amazon          Blend
1                 Amazon mix          Blend
2                Amazon, ICS          Blend
3                    Beniano        Beniano
4                      Blend          Blend
5    Blend-Forastero,Criollo          Blend
6                      CCN51          CCN51
7                    Criollo        Criollo
8           Criollo (Amarru)        Criollo
9       Criollo (Ocumare 61)        Criollo
10      Criollo (Ocumare 67)        Criollo
11      Criollo (Ocumare 77)        Criollo
12         Criollo (Ocumare)        Criollo
13       Criollo (Porcelana)        Criollo
14            Criollo (Wild)        Criollo
15                Criollo, +        Criollo
16        Criollo, Forastero        Criollo
17       Criollo, Trinitario          Blend
18                       EET            EET
19                 Forastero      Forastero
20     Forastero (Amelonado)      Forastero
21        Forastero (Arriba)      Forastero
22    Forastero (Arriba) ASS      Forastero
23   Forastero (Arriba) ASSS      Forastero
24       Forastero (Catongo)      Forastero
25      Forastero (Nacional)      Forastero
26     Forastero (Parazinho)      Forastero
27    Forastero(Arriba, CCN)      Forastero
28     Forastero, Trinitario          Blend
29                    Matina         Matina
30                   NA_bean        NA_bean
31                  Nacional       Nacional
32         Nacional (Arriba)       Nacional
33                     Other          Other
34                Trinitario     Trinitario
35  Trinitario (85% Criollo)          Blend
36    Trinitario (Amelonado)     Trinitario
37      Trinitario (Scavina)     Trinitario
38       Trinitario, Criollo          Blend
39     Trinitario, Forastero          Blend
40      Trinitario, Nacional          Blend
41          Trinitario, TCGA     Trinitario
0 голосов
/ 15 сентября 2018

Источник вашей проблемы Criollo, +, используемый в качестве шаблона регулярного выражения.

Обратите внимание, что этот шаблон на самом деле означает:

  • найти Criollo и запятую,
  • затем найдите пробел, встречающийся 1 или более раз (+ в регулярном выражении является повторением считать за предыдущее выражение, в данном случае пробел).

Этот шаблон соответствует также Criollo, в Criollo, Forastero. Поскольку эта замена фактически удаляет , (запятую и пробел), вы получаете CriolloForastero.

Чтобы устранить проблему, измените этот шаблон на Criollo, \+ (заключите + в обратная косая черта, чтобы соответствовать им буквально).

['Criollo\+', 'Criollo'] в вашем списке замены, вероятно, не требуется.

Редактировать

Вы также можете попробовать другой подход:

Функция, применяемая к каждому полю bean_type, должна:

  1. Проверьте, содержит ли текст Blend (где угодно). Если это так, верните Blend.
  2. Найти все слова (последовательности букв) - имена бобов. Когда шаблон содержит одна группа захвата, результатом findall является список всех "результатов".
  3. Если найдено только одиночное слово (список результатов содержит только 1 товар), вернуть только этот товар.
  4. В противном случае ( найдено несколько имен бинов) return Blend.

Ниже приведен пример программы:

import pandas as pd
import re
def std_bean_name(text):
    """Generate standard bean name"""
    if re.search('Blend', text, re.IGNORECASE):
        return 'Blend'
    res = re.findall(r"([a-z]+)", text, re.IGNORECASE)
    if len(res) == 1:
        return res[0]
    else:
        return 'Blend'
# Source data
lst = ['Amazon', 'Amazon mix', 'Amazon, ICS', 'Beniano', 'Blend',
    'Blend-Forastero,Criollo', 'CCN51', 'Criollo', 'Criollo (Amarru)',
    'Criollo (Ocumare 61)', 'Criollo (Ocumare 67)',
    'Criollo (Ocumare 77)', 'Criollo (Ocumare)', 'Criollo (Porcelana)',
    'Criollo (Wild)', 'Criollo, +', 'Criollo, Forastero',
    'Criollo, Trinitario', 'EET', 'Forastero', 'Forastero (Amelonado)',
    'Forastero (Arriba)', 'Forastero (Arriba) ASS',
    'Forastero (Arriba) ASSS', 'Forastero (Catongo)',
    'Forastero (Nacional)', 'Forastero (Parazinho)',
    'Forastero(Arriba, CCN)', 'Forastero, Trinitario', 'Matina',
    'NA_bean', 'Nacional', 'Nacional (Arriba)', 'Other', 'Trinitario',
    'Trinitario (85% Criollo)', 'Trinitario (Amelonado)',
    'Trinitario (Scavina)', 'Trinitario, Criollo',
    'Trinitario, Forastero', 'Trinitario, Nacional', 'Trinitario, TCGA']
# Create a DataFrame
beans = pd.DataFrame(data=lst, columns=['bean_type'])
# Generate standard bean names
beans['type2'] = beans['bean_type'].apply(std_bean_name)
# Show the detailed result (source / standard type)
print(beans)
# List unique bean names
print(beans['type2'].unique())

Последняя строка печатает:

['Amazon' 'Blend' 'Beniano' 'CCN' 'Criollo' 'EET' 'Forastero' 'Matina'
 'Nacional' 'Other' 'Trinitario']

Я тестировал вышеуказанную программу под Python 3.6 и Jupyter Notebook .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...