在SAS中实现多账户开户日期宏变量存储及开户后10天交易数据提取的技术咨询
解决SAS中提取各账户开户日起10天交易数据的问题
其实你完全不用把每个account_open_date单独存成宏变量,有更简单高效的方案!我给你两种思路,优先推荐第一种非宏的关联筛选方法,如果你一定要用宏实现批量处理,第二种宏循环方案也能满足需求。
方法1:直接关联数据集筛选(最推荐)
这种方法不需要宏变量,直接通过账户ID匹配两个数据集,用日期函数判断交易日期是否在开户日到开户日+10天的范围内。首先要把字符型日期转换成SAS能识别的日期格式,再做关联筛选:
/* 第一步:清洗开户数据集,把字符日期转为SAS日期 */ data accounts_clean; set accounts; /* 替换成你的第一个开户数据集名称 */ /* SAS的date9.格式自动识别带st/nd/rd/th的日期 */ account_open_date_sas = input(account_open_date, date9.); format account_open_date_sas date9.; run; /* 第二步:清洗交易数据集,转换日期和余额格式 */ data transactions_clean; set transactions; /* 替换成你的第二个交易数据集名称 */ transaction_date_sas = input(transaction_date, date9.); /* 去掉£符号,把余额转为数值型 */ customer_bal = input(customer_bal, comma8.); format transaction_date_sas date9. customer_bal dollar8.; run; /* 第三步:关联两个数据集,筛选目标数据 */ proc sql; create table account_10day_bal as select a.accountid, a.account_open_date_sas as open_date, t.transaction_date_sas as trans_date, t.customer_bal from accounts_clean a inner join transactions_clean t on a.accountid = t.accountid /* 判断交易日期是否在开户日到开户日+10天内 */ where t.transaction_date_sas between a.account_open_date_sas and intnx('day', a.account_open_date_sas, 10, 's') order by a.accountid, t.transaction_date_sas; quit;
这个方法一步到位,SAS处理数据集关联的效率远高于宏循环,尤其是你只有50个账户的情况,完全没必要用宏来绕圈子。
方法2:用宏循环批量处理每个账户
如果你确实需要用宏实现,那可以先把所有账户ID和对应的开户日期提取到宏变量列表中,再循环处理每个账户:
/* 第一步:提取所有账户ID和开户日期到宏变量 */ proc sql noprint; /* 把账户ID和转换后的SAS日期分别存入两个宏变量,用空格分隔 */ select accountid, input(account_open_date, date9.) into :account_ids separated by ' ', :open_dates separated by ' ' from accounts; /* 替换成你的开户数据集名称 */ /* 统计账户总数,用于循环次数 */ select count(*) into :total_accounts from accounts; quit; /* 第二步:编写宏循环处理每个账户 */ %macro extract_10day_bal; /* 先创建一个空的结果数据集,用于后续合并 */ data account_10day_bal; length accountid $7 open_date trans_date date9. customer_bal 8; stop; run; /* 循环每个账户 */ %do i = 1 %to &total_accounts.; /* 获取当前循环的账户ID和开户日期 */ %let current_id = %scan(&account_ids., &i., ' '); %let current_open = %scan(&open_dates., &i., ' '); /* 计算开户日+10天的截止日期 */ %let end_date = %sysfunc(intnx(day, ¤t_open., 10, s), date9.); /* 提取当前账户的10天内交易数据 */ data temp_bal; set transactions; /* 替换成你的交易数据集名称 */ where accountid = "¤t_id." and input(transaction_date, date9.) between ¤t_open. and &end_date.; /* 转换日期和余额为SAS格式 */ trans_date = input(transaction_date, date9.); customer_bal = input(customer_bal, comma8.); format trans_date date9. customer_bal dollar8.; keep accountid trans_date customer_bal; run; /* 把当前账户的数据合并到结果数据集 */ data account_10day_bal; set account_10day_bal temp_bal; run; %end; %mend; /* 执行宏 */ %extract_10day_bal;
关键注意点:
- 日期转换:
date9.格式可以自动识别21st Nov 2020这种带后缀的日期,SAS会忽略st/nd/rd/th这些字符 - 余额处理:一定要把带£符号的字符型余额转换成数值型,否则无法进行后续统计分析
- 性能对比:方法1的效率远高于方法2,当账户数量增多时,宏循环的开销会明显变大,所以优先选择方法1
内容的提问来源于stack exchange,提问作者Swati Kanchan
相关产品推荐
相关产品推荐

