Группировка строк профилей, содержащих одинаковые слова, но встречающихся не по порядку Python

#python #nlp #difflib

#python #nlp #difflib

Вопрос:

У меня есть фрейм данных, содержащий столбец типов профилей, который выглядит следующим образом:

 0                                    Android Java
1                  Software Development Developer
2                            Full-stack Developer
3                      JavaScript Frontend Design
4                          Android iOS JavaScript
5                             Ruby JavaScript PHP
  

Я использовал NLP для нечеткого сопоставления похожих профилей, которые возвращали следующий фрейм данных сходства:

 left_side                       right_side                  similarity
7   JavaScript Frontend Design  Design JavaScript Frontend  0.849943
8   JavaScript Frontend Design  Frontend Design JavaScript  0.814599
9   JavaScript Frontend Design  JavaScript Frontend         0.808010
10  JavaScript Frontend Design  Frontend JavaScript Design  0.802881
12  Android iOS JavaScript      Android iOS Java            0.925126
15  Machine Learning Engineer   Machine Learning Developer  0.839165
21  Android Developer Developer Android Developer           0.872646
25  Design Marketing Testing    Design Marketing            0.817195
28  Quality Assurance           Quality Assurance Developer 0.948010
  

Хотя это помогло, переведя меня с 478 уникальных профилей на 461, я бы хотел сосредоточиться на таких профилях:

 Frontend Design JavaScript  Design Frontend JavaScript
  

Единственный инструмент, который я видел, который предназначен для решения этой проблемы, — это difflib?
Мой вопрос в том, какие другие методы были бы доступны, чтобы пройти и стандартизировать эти профили, состоящие из одних и тех же слов, но не по порядку, в одну стандартную строку.
Таким желаемым результатом было бы взять строку, содержащую «Дизайн», «Интерфейс» и «JavaScript», и заменить ее на «Дизайн интерфейса JavaScript».

Прямо сейчас я объединяю свой исходный фрейм данных с фреймом данных similarity, чтобы заменить все вхождения строки профиля в right_side на left_side, но это означает, что я заменяю right_side ниже («Java Python Data Science») на left_side ниже («JavaScript Python Data Science»).

 53  JavaScript Python Data Science  Java Python Data Science
  

Любая помощь будет с благодарностью!!!

РЕДАКТИРОВАТЬ *** У меня написано следующее, чтобы заменить все слова, встречающиеся как в words_to_keep, так и в столбце clean_talentpool[‘profile’], но, похоже, это не работает? Не мог бы кто-нибудь любезно указать, чего я не вижу? Я был бы очень признателен!

 def standardize_word_order(row):
    words_to_keep = [
        "javascript frontend design",
        "android ios javascript",
        "android developer developer",
        "android developer",
        "quality assurance",
        "quality assurance engineer",
        "architecture developer",
        "big data architecture developer",
        "data architecture developer",
        "software architecture developer",
        "javascript python data science",
        "frontend php javascript",
        "javascript android ios",
        "frontend design javascript",
        "java python data science",
        "javascript frontend android",
        ".net javascript frontend",
    ]
    for word in words_to_keep:
        if (sorted(word.replace(" ", ""))) == sorted(
            row.replace(" ", "")
        ) and word != row:
            row.replace(row, word)
    return row

clean_talentpool["profile"] = clean_talentpool["profile"].apply(
    lambda x: standardize_word_order(x)
)
  

Комментарии:

1. Насколько я вижу, я не думаю, что вам нужна лямбда-функция. Лямбды — это анонимная функция для инкапсуляции небольшого фрагмента логики, объявленного на лету, чтобы сохранить компактность кода.

Ответ №1:

В вашем случае я бы сосредоточился не на строке, а на символах. В основном, если две строки состоят из одних и тех же символов (перестановок), они совпадают.

 a = "Frontend Design JavaScript"
b = "Javascript Frontend Design"

sorted(a) == sorted(b)
#prints True
  

Вы можете рассмотреть возможность удаления пробела и выполнить другую предварительную обработку, например, в нижнем регистре.

 if sorted(a.lower().replace(" ","")) == sorted(b.lower().replace(" ","")):
    # they are the same, do something
  

В соответствии с вашим примером реализация может быть:

 def standardize_word_order(row):
    words_to_keep = [
        "javascript frontend design",
        "android ios javascript",
        "android developer developer",
        "android developer",
        "quality assurance",
        "quality assurance engineer",
        "architecture developer",
        "big data architecture developer",
        "data architecture developer",
        "software architecture developer",
        "javascript python data science",
        "frontend php javascript",
        "javascript android ios",
        "frontend design javascript",
        "java python data science",
        "javascript frontend android",
        ".net javascript frontend",
    ]
    for word in words_to_keep:
        if ((sorted(word.replace(" ", ""))) == sorted(
            row.replace(" ", "")
        ) and word != row):
            return word
    return row

clean_talentpool["profile"] = standardize_word_order(clean_talentpool["profile"])
  

Комментарии:

1. Спасибо! Это отличная стратегия. Есть идеи, как я мог бы взять слова, удовлетворяющие условию if, и заменить их списком words_to_keep, показанным выше?