pandas实现面板数据各年度企业entry(进入)exit(退出)标识计算
问题背景
现有2016、2017、2018三个年度的企业观测DataFrame,所有表字段结构一致,ID字段为企业唯一标识,示例数据如下:
import pandas as pd df2016 = pd.DataFrame({"ID": [99,101,102,103,104], "A": [1,2,3,4,5], "B": [2,4,6,8,10], "year": [2016,2016,2016,2016,2016]}) df2017 = pd.DataFrame({"ID": [100,101,102,104], "A": [5,6,7,8], "B": [9,11,13,15], "year": [2017,2017,2017,2017]}) df2018 = pd.DataFrame({"ID": [100,106], "A": [6,8], "B": [13,15], "year": [2018,2018]})
实现目标
需要为拼接后的面板数据新增进入、退出标识字段,规则如下:
- 新增
entry字段:企业ID在上一年度数据中不存在、本年度存在则取值为1,否则取值为0 - 新增
exit字段:企业ID在本年度数据中存在、下一年度数据中不存在则取值为1,否则取值为0 - 首年、末年的边界场景可按业务合理逻辑处理,期望输出参考如下:
A B entry exit ID year 99 2016 1.0 2.0 1 1 101 2016 2.0 4.0 1 0 102 2016 3.0 6.0 1 0 103 2016 4.0 8.0 1 1 104 2016 5.0 10.0 1 0 100 2017 5.0 9.0 1 0 101 2017 6.0 11.0 0 1 102 2017 7.0 13.0 0 1 104 2017 8.0 15.0 0 1 100 2018 6.0 13.0 0 0 106 2018 8.0 15.0 1 0
当前进度
已完成三个年度数据拼接,并设置(ID, year)为多重索引,对应代码和结果如下:
df = pd.concat([df2016, df2017, df2018]) df.set_index(["ID", "year"], inplace=True)
运行后当前df结构:
A B ID year 99 2016 1 2 101 2016 2 4 102 2016 3 6 103 2016 4 8 104 2016 5 10 100 2017 5 9 101 2017 6 11 102 2017 7 13 104 2017 8 15 100 2018 6 13 106 2018 8 15
实现方案
直接基于现有索引结构,先预存每个年度的企业ID集合,逐行判断进入、退出状态即可,代码如下:
# 获取排序后的年度列表,以及每个年度对应的企业ID集合 years = sorted(df.index.get_level_values("year").unique()) year_id_map = {y: set(df.loc[pd.IndexSlice[:, y], :].index.get_level_values("ID")) for y in years} # 计算entry字段:首年所有企业记为新进入,其余年份判断上一年是否存在该ID df["entry"] = df.apply( lambda x: 1 if x.name[1] == years[0] or x.name[0] not in year_id_map[x.name[1]-1] else 0, axis=1 ) # 计算exit字段:末年所有企业记为未退出,其余年份判断下一年是否存在该ID df["exit"] = df.apply( lambda x: 0 if x.name[1] == years[-1] or x.name[0] in year_id_map[x.name[1]+1] else 1, axis=1 )
运行后得到的结果和期望输出完全一致,边界逻辑匹配示例规则:首年出现的企业全部标记为进入,末年留存的企业全部标记为未退出。
内容的提问来源于stack exchange,提问作者Smithey
相关产品推荐
相关产品推荐

