SAS中基于现有数组动态生成对应命名百分比变量方法咨询
解决方案
你遇到的核心问题是第二种写法混淆了宏变量编译时机和DATA步执行时机:&var_name. 会在DATA步编译阶段就完成解析,此时CALL SYMPUT还没执行,运行阶段修改的宏变量无法回写到已编译的赋值语句中,因此只会生成最后一个变量。
推荐用提前拼接变量名的方案,完全适配动态场景,逻辑简洁可直接嵌入宏使用:
步骤1:预生成百分比变量名列表
proc sql noprint; /* 自动匹配所有RTL_开头的变量,生成对应PCT_开头的变量名 */ select cats('PCT_', scan(name, 2, '_')) into :pct_vars separated by ' ' from dictionary.columns where libname = 'WORK' /* 数据集所在库名,带库名的数据集可自行修改匹配规则 */ and memname = 'HAVE' /* 输入数据集名 */ and upcase(name) like 'RTL_%'; quit;
步骤2:双数组对应计算百分比
data want; set have; array rtls[*] rtl_:; /* 直接用预生成的变量列表定义百分比数组,变量名和原变量一一对应 */ array pcts[*] &pct_vars.; total_sales = sum(of rtls[*]); /* 加判断避免除以0报错 */ if total_sales ne 0 then do i = 1 to dim(rtls); pcts[i] = rtls[i] / total_sales; /* 需要显示为百分比格式可改为 pcts[i] = rtls[i] / total_sales * 100; 后续自行加format即可 */ end; else do i = 1 to dim(rtls); pcts[i] = .; end; drop i total_sales; /* 不需要这两个辅助变量可保留drop语句,需要就删掉 */ run;
宏封装版本(直接可在宏逻辑中调用)
如果需要复用逻辑,可直接封装为通用宏:
%macro calc_rtl_pct(in_ds=, out_ds=, prefix=RTL_); proc sql noprint; select cats('PCT_', scan(name, 2, '_')) into :pct_vars separated by ' ' from dictionary.columns where libname = upcase(scan("&in_ds.", 1, '.')) and memname = upcase(scan("&in_ds.", 2, '.')) and upcase(name) like upcase("&prefix.%"); quit; data &out_ds.; set &in_ds.; array origin[*] &prefix.:; array pct[*] &pct_vars.; total = sum(of origin[*]); if total ne 0 then do i=1 to dim(origin); pct[i] = origin[i]/total; end; else do i=1 to dim(origin); pct[i] = .; end; drop i total; run; %mend; /* 调用示例 */ %calc_rtl_pct(in_ds=have, out_ds=want);
内容的提问来源于stack exchange,提问作者J_Lard
相关产品推荐
相关产品推荐

