首页 > 解决方案 > 在 Python Pandas 中创建优先级

问题描述

我有一个大型数据集,其中显示了个人拥有的每个学位以及获得学位的年份。此外,每个人都有一个对应的ID。我正在尝试使用完成学位的年份和完成学位的平均年龄来查找每个人的出生年份。数据集如下所示:

对于平均年龄,我假设博士在 33 岁完成,硕士在 30 岁完成,学士在 22 岁完成。

person_id   degree                       degree_completion   year_of_birth
1           PhD                          2006                1973
1           BSc                          1999                1977
2           Ph.D.                        1995                1962
2           MBA                          2000                1970
2           B.A.                         1987                1965
3           Bachelor of Engineering      2005                1983
4           AB                           1997                1975
4           Doctor of Philosophy (PhD)   2003                1970                          

我已经创建了计算每个人的出生年份的系统,但我不知道如何创建一个优先系统,以便它选择正确的出生年份,因为可以为个人拥有的每个学位计算不同的出生年份。我想要以下优先级:学士出生年份>博士出生年份>硕士出生年份。

我用 groupby 函数和 Categorial 数据类型尝试了很多东西。此外,数据集中有数百种不同的学位形式,因此我一直依赖于使用正则表达式来计算出生年份和创建优先级系统。这是我目前所拥有的,但我找不到将正则表达式实现到其中的方法:

category1 = "^B[a-z]*|AB|A.B.|A.B|S.B."
category2 = "^P[a-z]*|Doctor of Philosophy[a-z]*"
category3 = "^M[a-z]*|Master[a-z]*"

file['edu_degree'] = pd.Categorical(file['edu_degree'], ordered=True, categories=[category1, category2, category3])

file.groupby('person_id')['edu_degree'].transform('max')

此外,这将是我想要的输出(根据优先级替换出生年份):

person_id   degree                       degree_completion   year_of_birth
1           PhD                          2006                1977
1           BSc                          1999                1977
2           Ph.D.                        1995                1965
2           MBA                          2000                1965
2           B.A.                         1987                1965
3           Bachelor of Engineering      2005                1983
4           AB                           1997                1975
4           Doctor of Philosophy (PhD)   2003                1975                          

标签: pythonpandaspython-3.8

解决方案


要应用正则表达式,您可以创建一个函数 ( get_diploma) 一个接一个地测试它们。理想情况下,按最可能的顺序排列(学士学位优先)。

然后您可以按 person_id 分组并找到具有最高优先级的行(get_expected_age函数)。

import re

category1 = "^B[a-z]*|AB|A.B.|A.B|S.B."
category2 = "^P[a-z]*|Doctor of Philosophy[a-z]*"
category3 = "^M[a-z]*|Master[a-z]*"

diplomas = {category1: 'Bachelor', category2: 'PhD', category3: 'Master'}
ages = {'PhD': 33, 'Master': 30, 'Bachelor': 22}


def get_diploma(s):
    # for first matching regexp, return diploma
    for k in diplomas:
        if re.match(k, s):
            return diplomas[k]
    

        
df['degree_standardized'] = pd.Categorical(df['degree'].map(get_diploma),
                                           ordered=True,
                                           categories=['Master', 'PhD', 'Bachelor'])
# map the age from the standardized degree. NB. this could be fused with the previous step.
df['expected_age'] = df['degree_standardized'].map(ages)

def get_expected_age(d):
    # get degree with highest priority
    s = d.sort_values(by='degree_standardized').iloc[-1]
    d['year_of_birth'] = s['degree_completion']-s['expected_age']
    return d

df.groupby('person_id').apply(get_expected_age)

输出:

   person_id                      degree  degree_completion  year_of_birth degree_standardized expected_age
0          1                         PhD               2006           1977                 PhD           33
1          1                         BSc               1999           1977            Bachelor           22
2          2                       Ph.D.               1995           1965                 PhD           33
3          2                         MBA               2000           1965              Master           30
4          2                        B.A.               1987           1965            Bachelor           22
5          3     Bachelor of Engineering               2005           1983            Bachelor           22
6          4                          AB               1997           1975            Bachelor           22
7          4  Doctor of Philosophy (PhD)               2003           1975                 PhD           33

推荐阅读