Найти похожие фразы в столбце в Pandas - PullRequest
1 голос
/ 18 марта 2020

Я использую Pandas для работы с фреймом данных, в котором есть столбец с названием компаний.

Для каждого названия компании доступно несколько версий. Например, df:

df = pd.DataFrame({'id':['a','b','c','d','e','f'],'company name':['name1', ' Name1 LTD', 'name1, ltd.','name 1 LT.D.',' name2 p.p.c', 'name2 ppc.']})

Мне было интересно, есть ли простой способ найти похожие имена и присвоить им уникальный идентификатор? Для примера выше я хотел бы получить что-то вроде:

dg = pd.DataFrame({'id':['a','a','a','a','e','e'],'company name':['name1', ' Name1 LTD', 'name1, ltd.','name 1 LT.D.',' name2 p.p.c', 'name2 ppc.']})

Спасибо,

Ответы [ 2 ]

1 голос
/ 18 марта 2020

Я чувствую, что ваша проблема, как и любая проблема программирования, должна быть разбита на более мелкие части. Я буду разбивать это шаг за шагом, как я понял, И как я подхожу к нему.

Шаг 1. Очистить (сделать единообразным) ваши company name значения. Вот хорошая статья о очистке данных и почему это важно.

Шаг 2. Составьте карту id на основе уникальных названий компаний (этот шаг прост после выполнения шага 1)


import pandas as pd

df = pd.DataFrame({'id':['a','b','c','d','e','f'],'company_name':['na,me1', ' Name1 LTD', 'name1, ltd.','name 1 LT.D.',' name2 p.p.c', 'name2 ppc.']})

Шаг 1.
Очистите его, используя extract с regex
, имейте в виду что ниже regex захватывает только предоставленную вами небольшую выборку, и вам может потребоваться разработать шаблон для работы с полным набором данных

df['new_company_name'] = (df['company_name']
                         .str.lower()                    # lowercase to standardize
                         .str.replace(' |,','')          # remove extra characters, this may vary for your full dataset
                         .str.extract(r'^(\w+\d{1})'))   # pattern to extract the vital part of the name, this also will vary based on your data

print(df)

  id  company_name new_company_name
0  a         name1            name1
1  b     Name1 LTD            name1
2  c   name1, ltd.            name1
3  d  name 1 LT.D.            name1
4  e   name2 p.p.c            name2
5  f    name2 ppc.            name2

Шаг 2
It Рекомендуется использовать числовые значения вместо str из-за производительности

Вариант 1 с использованием groupby() с ngroup()

df['new_id'] = df.groupby('new_company_name').ngroup()

Вариант 2 используя zip(), dict(), а затем map()

unique_names = df.new_company_name.unique()
mapper = dict(
    zip(unique_names,
        [name_id for name_id in range(len(unique_names))]
    )
)
df['new_id'] = df['new_company_name'].map(mapper)

Тот же результат для Опция 1 или Опция 2

print(df)

  id  company_name new_company_name  new_id
0  a         name1            name1       0
1  b     Name1 LTD            name1       0
2  c   name1, ltd.            name1       0
3  d  name 1 LT.D.            name1       0
4  e   name2 p.p.c            name2       1
5  f    name2 ppc.            name2       1

Надеюсь, это поможет.

1 голос
/ 18 марта 2020

Одна из вещей, которые я сделал, - это использование regex или функции, которая обрабатывает необработанные строки, которые удаляют все лишние, такие как ltd и произвольные специальные символы. Затем создайте обработанную строку, которая является их «истинным именем», и создайте индекс идентификаторов на основе «истинного имени».

Или вы можете использовать fuzzywuzzy, чтобы найти расстояние между двумя строками и построить набор кандидатов из сопоставляет и создает индекс уникальных имен на основе результатов сопоставления.

т.е.

def clean_str(x):
    x2 = x.lower()
    x2 = x2.replace('.', '')
    return x2
...