基于起止日期生成月度虚拟变量(R/Stata实现)
生成客户关系存续月度虚拟变量(R & Stata实现)
需求说明
给定记录客户与银行关系起止日期的数据集,需完成以下操作:
- 生成2016年7月至2019年12月期间的30个月度虚拟变量
- 变量命名格式为
YYYYMM(如201607、201608) - 客户关系存续对应月份时,变量值为1,否则为0
- 若
end month和end year均为0,视为关系持续至研究期末(2019年12月)
R语言实现
1. 加载数据集
df <- structure(list(id = c(1, 1, 2, 2, 2, 2, 3, 4, 4, 4, 4, 5), `start month` = c(1, 4, 5, 8, 12, 11, 10, 3, 5, 6, 2, 1), `start year` = c(1999, 2018, 2017, 2019, 1980, 2019, 2016, 2020, 2022, 2019, 2015, 2016), `end month` = c(4, 2, 0, 12, 0, 12, 5, 0, 0, 11, 5, 9), `end year` = c(2020, 2019, 0, 2022, 0, 2019, 2017, 0, 0, 2020, 2019, 2017)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -12L))
2. 生成虚拟变量代码
library(dplyr) library(lubridate) # 生成研究期的月度序列及变量名 study_months <- seq(ymd("2016-07-01"), ymd("2019-12-01"), by = "month") month_names <- format(study_months, "%Y%m") # 处理起止日期:替换0值为研究期末 df_processed <- df %>% mutate( start_date = ymd(paste(`start year`, `start month`, "01", sep = "-")), end_date = case_when( `end month` == 0 & `end year` == 0 ~ ymd("2019-12-01"), TRUE ~ ymd(paste(`end year`, `end month`, "01", sep = "-")) ) ) # 循环生成每个月度的虚拟变量 for (mn in month_names) { current_month <- ymd(paste0(mn, "01")) df_processed <- df_processed %>% mutate(!!mn := as.integer(start_date <= current_month & end_date >= current_month)) } # 保留原始列和虚拟变量,移除中间日期列 final_df <- df_processed %>% select(-start_date, -end_date)
代码说明
- 用
lubridate包将年月转换为标准日期格式,简化区间比较逻辑 - 用
case_when统一处理终止日期为0的特殊情况,替换为研究期末日期 - 循环遍历研究期每个月份,判断该月份是否落在客户关系存续区间内,生成对应虚拟变量
Stata实现
1. 加载数据集
* Example generated by -dataex-. To install: ssc install dataex clear input byte(id startmonth) int startyear byte endmonth int endyear 1 1 1999 4 2020 1 4 2018 2 2019 2 5 2017 0 0 2 8 2019 12 2022 2 12 1980 0 0 2 11 2019 12 2019 3 10 2016 5 2017 4 3 2020 0 0 4 5 2022 0 0 4 6 2019 11 2020 4 2 2015 5 2019 5 1 2016 9 2017 end
2. 生成虚拟变量代码
* 定义研究期起止年月 local start_year 2016 local start_month 7 local end_year 2019 local end_month 12 * 将起止年月转换为Stata月度日期格式(%tm) gen start_date = ym(startyear, startmonth) gen end_date = cond(endmonth == 0 & endyear == 0, ym(`end_year', `end_month'), ym(endyear, endmonth)) * 循环生成研究期所有月度虚拟变量 local current_year = `start_year' local current_month = `start_month' while `current_year' < `end_year' | (`current_year' == `end_year' & `current_month' <= `end_month') { * 生成变量名(YYYYMM格式) local var_name = string(`current_year') + string(`current_month', "%02.0f") * 转换当前年月为%tm格式 local current_tm = ym(`current_year', `current_month') * 判断关系是否存续,生成虚拟变量 gen `var_name' = (start_date <= `current_tm' & end_date >= `current_tm') * 推进到下一个月 if `current_month' == 12 { local current_year = `current_year' + 1 local current_month = 1 } else { local current_month = `current_month' + 1 } } * 移除中间日期列 drop start_date end_date
代码说明
- 用
ym()函数将年月转换为Stata专用的月度日期格式,便于数值化比较 - 用
cond()函数处理终止日期为0的特殊情况,统一替换为研究期末的月度日期 - 通过循环遍历研究期每个月份,生成符合命名规则的虚拟变量,核心逻辑为判断当前月份是否在客户关系存续区间内
内容的提问来源于stack exchange,提问作者R novice
相关产品推荐
相关产品推荐

