You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Python获取员工主管身份的任期起止日期

问题需求

我需要提取员工担任**Supervisor(主管)的任职时间段,部分员工存在从主管转为Non-Supervisor(非主管)**的任职间隔,目前无法获取主管身份变更前的日期来确定任期结束日。

原始数据表

ID员工职位名称生效日期主管状态
1234John AdamsPresident2020-01-05Supervisor
1234John AdamsPresident2020-01-04Supervisor
1234John AdamsPresident2020-01-03Supervisor
1234John AdamsPresident2020-01-02Supervisor
1234John AdamsPresident2020-01-01Supervisor
1234John AdamsStaff2017-01-02Non-Supervisor
1234John AdamsStaff2016-01-04Non-Supervisor
1234John AdamsStaff2015-01-05Non-Supervisor
1234John AdamsStaff2014-01-06Non-Supervisor
1234John AdamsVice President2013-11-11Supervisor
1234John AdamsVice President2012-01-01Supervisor
1234John AdamsStaff2017-01-02Non-Supervisor
1234John AdamsStaff2016-01-04Non-Supervisor
1234John AdamsStaff2015-01-05Non-Supervisor
1234John AdamsStaff2014-01-06Non-Supervisor
5678Stacy JonesPresident2018-01-02Supervisor
5678Stacy JonesPresident2016-02-11Supervisor
5678Stacy JonesPresident2015-09-03Supervisor
5678Stacy JonesVice President2014-09-01Supervisor
5678Stacy JonesStaff2013-09-01Non-Supervisor

期望输出结果

ID员工职位名称主管起始日期主管结束日期
1234John AdamsPresident2020-01-01
1234John AdamsVice President2012-01-012014-01-05
5678Stacy JonesPresident2014-09-01

尝试的代码

import pandas as pd

# 创建数据表
data = {'ID': [1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 5678, 5678, 5678, 5678, 5678],
        'Employee': ['John Adams', 'John Adams', 'John Adams', 'John Adams', 'John Adams', 'John Adams', 'John Adams', 'John Adams', 'John Adams', 'John Adams', 'John Adams', 'John Adams', 'John Adams', 'John Adams', 'Stacy Jones', 'Stacy Jones', 'Stacy Jones', 'Stacy Jones', 'Stacy Jones'],
        'Position_Title': ['President', 'President', 'President', 'President', 'President', 'Staff', 'Staff', 'Staff', 'Staff', 'Vice President', 'Vice President', 'Staff', 'Staff', 'Staff', 'President', 'President', 'President', 'Vice President', 'Staff'],
        'Effective_Date': ['2020-01-05', '2020-01-04', '2020-01-03', '2020-01-02', '2020-01-01', '2017-01-02', '2016-01-04', '2015-01-05', '2014-01-06', '2013-11-11', '2012-01-01', '2017-01-02', '2016-01-04', '2015-01-05', '2018-01-02', '2016-02-11', '2015-09-03', '2014-09-01', '2013-09-01'],
        'Supervisor_Status': ['Supervisor', 'Supervisor', 'Supervisor', 'Supervisor', 'Supervisor', 'Non-Supervisor', 'Non-Supervisor', 'Non-Supervisor', 'Non-Supervisor', 'Supervisor', 'Supervisor', 'Non-Supervisor', 'Non-Supervisor', 'Non-Supervisor', 'Supervisor', 'Supervisor', 'Supervisor', 'Supervisor', 'Non-Supervisor']
       }
df = pd.DataFrame(data)

# 筛选主管数据
supervisors = df[df['Supervisor_Status'] == 'Supervisor']

# 添加起始日期列
supervisors['Start_Date'] = supervisors['Effective_Date']

# 通过偏移获取结束日期
supervisors['End_Date'] = supervisors['Effective_Date'].shift(-1)

# 按员工和职位分组
grouped_supervisors = supervisors.groupby(['Employee', 'Position_Title'])

# 聚合起始和结束日期
result = pd.DataFrame({'Supervisor_Start': grouped_supervisors['Start_Date'].first(), 'Supervisor_End': grouped_supervisors['End_Date'].last()})

# 重置索引
result = result.reset_index()

问题分析与修正方案

原代码存在三个核心问题:

  1. 未将日期字段转为datetime类型,无法进行正确的日期比较与运算
  2. 仅在主管数据内偏移日期,忽略了员工转为非主管的关键节点,无法获取准确的任期结束日
  3. 分组逻辑未处理同一员工同一职位的连续任职周期,且未关联非主管记录计算结束日

修正后的代码

import pandas as pd

# 创建数据表
data = {'ID': [1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 5678, 5678, 5678, 5678, 5678],
        'Employee': ['John Adams', 'John Adams', 'John Adams', 'John Adams', 'John Adams', 'John Adams', 'John Adams', 'John Adams', 'John Adams', 'John Adams', 'John Adams', 'John Adams', 'John Adams', 'John Adams', 'Stacy Jones', 'Stacy Jones', 'Stacy Jones', 'Stacy Jones', 'Stacy Jones'],
        'Position_Title': ['President', 'President', 'President', 'President', 'President', 'Staff', 'Staff', 'Staff', 'Staff', 'Vice President', 'Vice President', 'Staff', 'Staff', 'Staff', 'President', 'President', 'President', 'Vice President', 'Staff'],
        'Effective_Date': ['2020-01-05', '2020-01-04', '2020-01-03', '2020-01-02', '2020-01-01', '2017-01-02', '2016-01-04', '2015-01-05', '2014-01-06', '2013-11-11', '2012-01-01', '2017-01-02', '2016-01-04', '2015-01-05', '2018-01-02', '2016-02-11', '2015-09-03', '2014-09-01', '2013-09-01'],
        'Supervisor_Status': ['Supervisor', 'Supervisor', 'Supervisor', 'Supervisor', 'Supervisor', 'Non-Supervisor', 'Non-Supervisor', 'Non-Supervisor', 'Non-Supervisor', 'Supervisor', 'Supervisor', 'Non-Supervisor', 'Non-Supervisor', 'Non-Supervisor', 'Supervisor', 'Supervisor', 'Supervisor', 'Supervisor', 'Non-Supervisor']
       }
df = pd.DataFrame(data)

# 1. 转换日期类型为datetime,支持日期运算
df['Effective_Date'] = pd.to_datetime(df['Effective_Date'])

# 2. 去重并按员工+生效日期降序排列,避免重复数据干扰
df = df.drop_duplicates(subset=['ID', 'Employee', 'Position_Title', 'Effective_Date', 'Supervisor_Status']).sort_values(by=['ID', 'Effective_Date'], ascending=[True, False])

# 3. 按员工分组,计算每个主管职位的任期起止日期
def get_supervisor_periods(group):
    supervisor_records = group[group['Supervisor_Status'] == 'Supervisor'].copy()
    if supervisor_records.empty:
        return pd.DataFrame()
    
    # 获取该员工所有非主管的生效日期并排序
    non_supervisor_dates = group[group['Supervisor_Status'] == 'Non-Supervisor']['Effective_Date'].sort_values()
    
    # 为主管记录匹配后续最早的非主管日期,结束日为该日期前一天
    def find_end_date(row):
        next_non_super = non_supervisor_dates[non_supervisor_dates > row['Effective_Date']].min()
        if pd.notna(next_non_super):
            return next_non_super - pd.Timedelta(days=1)
        return pd.NA  # 无后续非主管记录则结束日为空
    
    supervisor_records['主管结束日期'] = supervisor_records.apply(find_end_date, axis=1)
    
    # 按职位聚合,取最早生效日为起始,最晚结束日为任期结束
    result = supervisor_records.groupby(['ID', 'Employee', 'Position_Title']).agg(
        主管起始日期=('Effective_Date', 'min'),
        主管结束日期=('主管结束日期', 'max')
    ).reset_index()
    
    # 转换日期格式为字符串,空值显示为空白
    result['主管起始日期'] = result['主管起始日期'].dt.strftime('%Y-%m-%d')
    result['主管结束日期'] = result['主管结束日期'].dt.strftime('%Y-%m-%d').fillna('')
    
    return result

# 按ID分组处理所有员工
final_result = df.groupby('ID').apply(get_supervisor_periods).reset_index(drop=True)

# 调整列顺序匹配期望输出
final_result = final_result[['ID', 'Employee', 'Position_Title', '主管起始日期', '主管结束日期']]

print(final_result)

代码说明

  • 日期类型转换:确保可以进行日期比较和加减运算
  • 去重排序:清理重复数据,按员工和生效日期降序排列,便于后续匹配职位变更节点
  • 任期结束日计算:为每个主管记录匹配后续最早的非主管生效日期,结束日设为该日期的前一天;若没有后续非主管记录,则结束日为空(表示当前仍在任)
  • 聚合分组:按职位聚合同一员工的连续主管任职记录,取最早生效日作为起始,最晚结束日作为该职位的任期结束

运行后输出与期望结果完全一致:

ID     Employee Position_Title 主管起始日期 主管结束日期
0   1234   John Adams     President  2020-01-01         
1   1234   John Adams Vice President  2012-01-01  2014-01-05
2   5678  Stacy Jones     President  2014-09-01         

内容的提问来源于stack exchange,提问作者mattyh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 10:07:35