Поиск столбца для строки и классифицировать их по словарю ключей - PullRequest
0 голосов
/ 06 марта 2020

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

Итак, я создал словарь с терминами для поиска каждой позиции. уровень.

Первая версия словаря будет выглядеть следующим образом:

dicpositions = {'0 - CEO, Founder': ['CEO', 'Founder', 'Co-Founder', 'Cofounder', 'Owner'],
                '1 - Director of': ['Director', 'Head'], 
                '2 - Manager': ['Manager', 'Administrador'], 
                '3 - Engenheiro': ['Engenheiro', 'Engineering'], 
                '4 - Consultor': ['Consultor', 'Consultant'], 
                '5 - Estagiário': ['Estagiário', 'Intern'], 
                '6 - Desempregado': ['Self-Employed', 'Autônomo'], 
                '7 - Professor': ['Professor', 'Researcher'] }

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

Примерные данные кадра данных, который я читаю, будут:

sample = pd.Series(data = (['(blank)'], ['Estagiário'], ['Professor', 'Adjunto'], 
                           ['CEO', 'and', 'Founder'], ['Engenheiro', 'de', 'Produção'], 
                           ['Consultant'], ['Founder', 'and', 'CTO'], 
                           ['Intern'], ['Manager', 'Specialist'], 
                           ['Administrador', 'de', 'Novos', 'Negócios'], 
                           ['Administrador', 'de', 'Serviços']))

, который возвращает:

0                                [(blank)]
1                             [Estagiário]
2                     [Professor, Adjunto]
3                      [CEO, and, Founder]
4               [Engenheiro, de, Produção]
5                             [Consultant]
6                      [Founder, and, CTO]
7                                 [Intern]
8                    [Manager, Specialist]
9     [Administrador, de, Novos, Negócios]
10           [Administrador, de, Serviços]
dtype: object

I ' мы сделали следующий код:

import pandas as pd
plan = pd.read_excel('SpreadSheet Name.xlsx', sheet_name = 'Positions')

list0 = ['CEO', 'Founder', 'Co-Founder', 'Cofounder', 'Owner']
list1 = ['Director', 'Head']
list2 = ['Manager', 'Administrador']   
listgeral = [dic0, dic1, dic2]

def in_list(list_to_search,terms_to_search):     
    results = [item for item in list_to_search if item in terms_to_search]
    if len(results) > 0:
        return '0 - CEO, Founder'        
    else:
        pass
plan['PositionLevel'] = plan['Position'].str.split().apply(lambda x: in_list(x, listgeral[0]))

Фактический вывод:

                                          Position           PositionLevel
0                                        '(blank)'                None
1                                     'Estagiário'                None
2                              'Professor Adjunto'                None
3                                'CEO and Founder'         '0 - CEO, Founder'
4                         'Engenheiro de produção'                None
5                                     'Consultant'                None
6                                'Founder and CTO'         '0 - CEO, Founder'
7                                         'Intern'                None
8                             'Manager Specialist'                None
9                'Administrador de Novos Negócios'                None

Ожидаемый вывод:

                                            Position         PositionLevel
0                                          '(blank)'              None
1                                       'Estagiário'       '5 - Estagiário'
2                                'Professor Adjunto'       '7 - Professor'
3                                  'CEO and Founder'      '0 - CEO, Founder'
4                           'Engenheiro de produção'       '3 - Engenheiro'
5                                       'Consultant'       '4 - Consultor'
6                                  'Founder and CTO'      '0 - CEO, Founder'
7                                           'Intern'       '5 - Estagiário'
8                               'Manager Specialist'        '2 - Manager'
9                  'Administrador de Novos Negócios'        '2 - Manager'

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

Я пытался чтобы применить следующий код к этой программе:

dictest = {'0 - CEO, Founder': ['CEO', 'Founder', 'Co-Founder', 'Cofounder', 'Owner'], 
           '1 - Director of': ['Director', 'Head'], 
           '2 - Manager': ['Manager', 'Administrador']}

def in_dic (x, dictest):
    for key in dictest:
        for elem in dictest[key]:
            if elem == x:
                return key
    return False

Где вывод in_dic('CEO', dictest) равен '0 - CEO, Founder'

И, например, вывод in_dic('Banana', dictest) равен False

Но я не мог выйти из этого и применить эту функцию in_dic() к моей проблеме.

Я был бы очень признателен за помощь.

Большое спасибо.

1 Ответ

0 голосов
/ 06 марта 2020

Я взял на себя смелость немного реорганизовать ваш вклад, но вот что у меня получилось (возможно, оно немного перегружено). Короче говоря, мы используем библиотеку с именем jellyfi sh (pip3 install jellyfish, код взят из this answer) для нечеткого сопоставления строк, чтобы сопоставить позиции в вашем листе Excel с позициями в вашем dicpositions, а затем просто сопоставьте их с категорией в том же самом словаре. Вот импорт и функция сопоставления:

import pandas as pd
import numpy as np
import jellyfish


# Function for fuzzy-matching strings
def get_closest_match(x, list_strings):
    best_match = None
    highest_jw = 0

    # Keep an eye out for "blank" values, they can be strings, e.g. "(blank)", or e.g. NaN values
    no_values = ["(blank)", np.nan, None]
    if x in no_values:
        return "(blank)"

    # Find which string most closely matches our input and return it
    for current_string in list_strings:
        current_score = jellyfish.jaro_winkler(x, current_string)

        if current_score > highest_jw:
            highest_jw = current_score
            best_match = current_string

    return best_match

Хорошо, а вот ваш dicpositions, который для удобства я перевожу в длинном формате DataFrame:

# Translations between keywords and their category, as dict, as provided in question
dicpositions = {'0 - CEO, Founder': ['CEO', 'Founder', 'Co-Founder', 'Cofounder', 'Owner'],
                '1 - Director of': ['Director', 'Head'],
                '2 - Manager': ['Manager', 'Administrador'],
                '3 - Engenheiro': ['Engenheiro', 'Engineering'],
                '4 - Consultor': ['Consultor', 'Consultant'],
                '5 - Estagiário': ['Estagiário', 'Intern'],
                '6 - Desempregado': ['Self-Employed', 'Autônomo'],
                '7 - Professor': ['Professor', 'Researcher'],
                'Not found"': ["(blank)"]  # <-- I added this to deal with blank values
}

# Let's expand the dict above to a DF, which makes for easier merging later
positions = []
aliases = []
for key, val in dicpositions.items():
    for v in val:
        positions.append(key)
        aliases.append(v)
# This will serve as our mapping table
lookup_table = pd.DataFrame({
    "position": positions,
    "alias": aliases
})
print(lookup_table)

Вместо того, чтобы словарь, это долгоформатный DataFrame. Этот формат позволяет действительно легко сопоставлять категории с различными ключевыми словами позже:

            position          alias
0   0 - CEO, Founder            CEO
1   0 - CEO, Founder        Founder
2   0 - CEO, Founder     Co-Founder
3   0 - CEO, Founder      Cofounder
4   0 - CEO, Founder          Owner
5    1 - Director of       Director
6    1 - Director of           Head
7        2 - Manager        Manager
8        2 - Manager  Administrador
9     3 - Engenheiro     Engenheiro
10    3 - Engenheiro    Engineering
11     4 - Consultor      Consultor
12     4 - Consultor     Consultant
13    5 - Estagiário     Estagiário
14    5 - Estagiário         Intern
15  6 - Desempregado  Self-Employed
16  6 - Desempregado       Autônomo
17     7 - Professor      Professor
18     7 - Professor     Researcher
19        Not found"        (blank)

Давайте проверим некоторые входные данные и посмотрим, как работает сопоставление. Мы проверяем каждую строку в вашем вводе со строками в столбце alias и возвращаем любое значение в столбце alias, наиболее точно соответствующее нашим входным данным (мы будем использовать это позже, чтобы найти категорию, или position):

# Test input, as a list, you might have to wrangle it from your format to a list, though
test_df = pd.DataFrame({"test_position": ["(blank)", 'Estagiário', 'Professor Adjunto', 'CEO and Founder', 'Engenheiro de produção', 'Consultant', 'Founder and CTO', 'Intern', 'Manager Specialist', 'Administrador de Novos Negócios']})

# Match our test input with our mapping table, create a new column 'best_match' representing the value in our mapping table that most closely matches our input
test_df["best_match"] = test_df.test_position.map(lambda x: get_closest_match(x, lookup_table.alias))
print(test_df)

В нашу test_df добавлен новый столбец, указывающий, какой alias в нашей справочной таблице наиболее похож на наш test_position ввод:

                    test_position     best_match
0                          (blank)        (blank)
1                       Estagiário     Estagiário
2                Professor Adjunto      Professor
3                  CEO and Founder            CEO
4           Engenheiro de produção     Engenheiro
5                       Consultant     Consultant
6                  Founder and CTO        Founder
7                           Intern         Intern
8               Manager Specialist        Manager
9  Administrador de Novos Negócios  Administrador

Чтобы получить категорию, мы просто объединяем наш столбец best_match в наших данных тестирования со столбцом alias нашей справочной таблицы:

result = test_df.merge(lookup_table, left_on="best_match", right_on="alias", how="left")

В результате:

                    test_position     best_match          alias          position
0                          (blank)        (blank)        (blank)         Not found
1                       Estagiário     Estagiário     Estagiário    5 - Estagiário
2                Professor Adjunto      Professor      Professor     7 - Professor
3                  CEO and Founder            CEO            CEO  0 - CEO, Founder
4           Engenheiro de produção     Engenheiro     Engenheiro    3 - Engenheiro
5                       Consultant     Consultant     Consultant     4 - Consultor
6                  Founder and CTO        Founder        Founder  0 - CEO, Founder
7                           Intern         Intern         Intern    5 - Estagiário
8               Manager Specialist        Manager        Manager       2 - Manager
9  Administrador de Novos Negócios  Administrador  Administrador       2 - Manager
...