Нечеткая логика Wuzzy c в одном фрейме данных pandas для замены похожих значений на наиболее часто встречающийся экземпляр - PullRequest
0 голосов
/ 17 апреля 2020

Я столкнулся с проблемой применения нечетких логик c для очистки данных в python. Мои данные выглядят примерно так

data=pd.DataFrame({'Employer':['Deloitte','Accenture','Accenture Solutions Ltd','Accenture USA', 'Ernst & young',' EY', 'Tata Consultancy Services','Deloitte Uk'], "Count":['140','120','50','45','30','20','10','5']})
data

Я использую нечеткие логики c для сравнения значений во фрейме данных. В конечном выводе должен быть третий столбец с таким результатом:

data_out=pd.DataFrame({'Employer':['Deloitte','Accenture','Accenture Solutions Ltd','Accenture USA', 'Ernst & young',' EY', 'Tata Consultancy Services','Deloitte Uk'], "New_Column":["Deloitte",'Accenture','Accenture','Accenture','Ernst & young','Ernst & young','Tata Consultancy Services','Deloitte']})
data_out

Поэтому, если вы видите, я хочу, чтобы менее встречающиеся значения имели новую запись в качестве нового столбца с наиболее встречающимся значением его типа. Вот где нечеткая логика c полезна.

Ответы [ 2 ]

0 голосов
/ 18 апреля 2020

Большинство ваших дублирующих компаний можно довольно легко обнаружить с помощью нечеткого сопоставления строк, однако замена Ernst & young <-> EY на самом деле совсем не похожа, поэтому я собираюсь проигнорировать эту замену здесь. В этом решении используется моя библиотека RapidFuzz , но вы можете реализовать нечто подобное, используя FuzzyWuzzy aswell (с небольшим количеством кода, поскольку он не имеет процессора extractIndices).

import pandas as pd
from rapidfuzz import process, utils

def add_deduped_employer_colum(data):
    values = data.values.tolist()
    employers = [employer for employer, _ in values]

    # preprocess strings beforehand (lowercase + remove punctuation),
    # so this is not done multiple times
    processed_employers = [utils.default_process(employer)
        for employer in employers]
    deduped_employers = employers.copy()

    replaced = []
    for (i, (employer, processed_employer)) in enumerate(
            zip(employers, processed_employers)):
        # skip elements that already got replaced
        if i in replaced:
            continue

        duplicates = process.extractIndices(
            processed_employer, processed_employers[i+1:],
            processor=None, score_cutoff=90, limit=None)

        for (c, _) in duplicates:
            deduped_employers[i+c+1] = employer
            """
            by replacing the element with an empty string the index from
            extractIndices stays correct but it can be skipped a lot 
            faster, since the compared strings will have very different
            lengths
            """
            processed_employers[i+c+1] = ""
            replaced.append(i+c+1)

    data['New_Column'] = deduped_employers

data=pd.DataFrame({
    'Employer':['Deloitte','Accenture','Accenture Solutions Ltd','Accenture USA', 'Ernst & young',' EY', 'Tata Consultancy Services','Deloitte Uk'],
    "Count":['140','120','50','45','30','20','10','5']})

add_deduped_employer_colum(data)
print(data)

, который приводит к следующему кадру данных:

                    Employer Count                 New_Column
0                   Deloitte   140                   Deloitte
1                  Accenture   120                  Accenture
2    Accenture Solutions Ltd    50                  Accenture
3              Accenture USA    45                  Accenture
4              Ernst & young    30              Ernst & young
5                         EY    20                         EY
6  Tata Consultancy Services    10  Tata Consultancy Services
7                Deloitte Uk     5                   Deloitte
0 голосов
/ 17 апреля 2020

Я не использовал нечеткий, но могу помочь следующим образом

Данные

df=pd.DataFrame({'Employer':['Accenture','Accenture Solutions Ltd','Accenture USA', 'hjk USA', 'Tata Consultancy Services']})
df

Вы не дали объяснения, почему Тата остается с полным именем. Поэтому я предполагаю, что он особенный, и маскирую его.

m=df.Employer.str.contains('Tata')

Затем я использую np.where для замены чего-либо после имени для остальных

df['New_Column']=np.where(m, df['Employer'], df['Employer'].str.replace(r'(\s+\D+)',''))
df

Вывод

enter image description here

...