如何在R中基于多条件按客户级创建DEFAULT_DATE列?
在R语言中按客户级别生成最早违约日期列的实现方案
先明确你的需求:基于客户分组,给每个客户的所有贷款记录添加DEFAULT_DATE列——如果客户有至少一笔违约贷款,就取该客户最早的违约日期;如果没有违约,就填-。
原始数据集
CUSTOMER LOAN DATE LOAN_DEFAULT CUSTOMER_DEFAULT 1 101 201601 Y Y 1 102 201603 N Y 1 101 201501 Y Y 2 201 201601 N N 2 202 201603 N N
预期输出
CUSTOMER LOAN DATE LOAN_DEFAULT CUSTOMER_DEFAULT DEFAULT_DATE 1 101 201601 Y Y 201501 1 102 201603 N Y 201501 1 103 201501 Y Y 201501 2 201 201601 N N - 2 202 201603 N N -
下面是两种实用的实现方式:
方法一:使用dplyr(tidyverse风格)
这是数据处理中最常用的方式,代码可读性高,逻辑清晰:
# 先安装并加载dplyr包(如果还没安装的话) # install.packages("dplyr") library(dplyr) # 第一步:构造你的原始数据集 df <- data.frame( CUSTOMER = c(1, 1, 1, 2, 2), LOAN = c(101, 102, 101, 201, 202), DATE = c(201601, 201603, 201501, 201601, 201603), LOAN_DEFAULT = c("Y", "N", "Y", "N", "N"), CUSTOMER_DEFAULT = c("Y", "Y", "Y", "N", "N"), stringsAsFactors = FALSE ) # 第二步:分组计算并生成新列 df_result <- df %>% group_by(CUSTOMER) %>% # 按客户ID分组 mutate( DEFAULT_DATE = ifelse( any(LOAN_DEFAULT == "Y"), # 判断当前客户是否有违约记录 min(DATE[LOAN_DEFAULT == "Y"]), # 取该客户最早的违约日期 "-" # 无违约则填"-" ) ) %>% ungroup() # 取消分组,回到普通数据框 # 查看最终结果 print(df_result)
代码说明:
group_by(CUSTOMER):把数据按客户分组,后续的计算都在客户内部进行any(LOAN_DEFAULT == "Y"):快速判断客户是否存在违约贷款DATE[LOAN_DEFAULT == "Y"]:筛选出当前客户所有违约贷款的日期,再用min()取最早的那个- 最后用
ungroup()取消分组,避免后续操作受分组影响
方法二:基础R实现
如果不想加载额外包,用基础R的ave()函数也能实现:
# 构造原始数据集(和上面一致) df <- data.frame( CUSTOMER = c(1, 1, 1, 2, 2), LOAN = c(101, 102, 101, 201, 202), DATE = c(201601, 201603, 201501, 201601, 201603), LOAN_DEFAULT = c("Y", "N", "Y", "N", "N"), CUSTOMER_DEFAULT = c("Y", "Y", "Y", "N", "N"), stringsAsFactors = FALSE ) # 直接生成DEFAULT_DATE列 df$DEFAULT_DATE <- with(df, ave( DATE, CUSTOMER, FUN = function(x) { # 获取当前客户对应的所有违约标记 current_cust <- unique(CUSTOMER) default_flags <- LOAN_DEFAULT[CUSTOMER == current_cust] # 筛选违约日期 default_dates <- x[default_flags == "Y"] # 判断并返回结果 if (length(default_dates) > 0) { as.character(min(default_dates)) # 转成字符型和"-"统一类型 } else { "-" } } )) # 查看结果 print(df)
代码说明:
ave()函数可以按指定分组(这里是CUSTOMER)对目标列(这里是DATE)应用自定义函数- 自定义函数里先筛选当前客户的违约标记,再提取对应的日期,最后判断是否有违约日期并返回对应结果
两种方法都能得到你想要的预期输出,推荐用dplyr的方式,代码更简洁易读,后续维护也方便。
内容的提问来源于stack exchange,提问作者S.Lee
相关产品推荐
相关产品推荐

