SAS迭代运行时如何生成唯一随机向量并绘制对应散点图
问题原因
你跑出来所有图都一样,是几个SAS运行逻辑的坑叠在一起导致的:
- 你当前
generate_scatter_plot宏里把随机点生成的调用注释掉了,全程只在第一次运行时生成过一次my_data数据集,后面20次绘图全在读这同一个固定数据集 - 就算你把那行注释打开,
call execute的执行时序也会出问题:数据步里用call execute压入的代码,宏解析逻辑会在当前数据步运行时立刻执行,而PROC/DATA步会排队等当前数据步跑完再按顺序执行。最终效果是20次随机点生成的PROC IML会先全部跑完,最后一次生成的my_data直接覆盖前19次的结果,之后20次sgplot再全部读这最后一个数据集,出来的图当然全一样 - 你写的随机点生成逻辑本身还有bug:
randgen只生成了6个单维度随机值,后续读数据是按x、y成对读,6个值只能凑3个点;而且直接把IML向量塞到datalines里没有做格式分隔,SAS读入时会直接解析失败。
修正方案
不要拆成两个宏来回调用,把单组的随机数生成、绘图逻辑整合到同一个宏里,同时规避call execute的时序问题即可,下面是两种可直接运行的实现:
方案1:不用IML,最简洁实现
不需要PROC IML,直接用数据步生成随机数,逻辑更简单不容易出错:
/* 取当前时间戳作为基础随机种子,保证每次运行结果不同,固定写数值比如123即可复现固定结果 */ %let base_seed = %sysfunc(floor(%sysfunc(datetime()))); %macro plot_one_group(group_id); /* 生成当前组的随机点数据集,加组号后缀避免覆盖 */ data point_set_&group_id.; call streaminit(&base_seed. + &group_id.); /* 每组用独立偏移种子,保证随机数不重复 */ do point_no = 1 to 6; /* 每组生成6个点,按需修改数量即可 */ x = rand('Uniform'); y = rand('Uniform'); output; end; run; /* 绘制散点图 */ proc sgplot data=point_set_&group_id. noautolegend; title "第&group_id.组随机点散点图"; scatter x=x y=y; run; /* 不需要保留临时数据集就打开下面这行,自动清理 */ /* proc datasets nolist lib=work; delete point_set_&group_id.; quit; */ %mend; /* 循环生成20组图,用%nrstr包裹宏调用解决时序问题 */ data _null_; do i = 1 to 20; call execute('%nrstr(%plot_one_group('||i||'))'); end; run;
方案2:保留PROC IML的实现
如果你需要用IML做后续计算,可以直接在IML里输出数据集,不用绕datalines传值:
%let base_seed = %sysfunc(floor(%sysfunc(datetime()))); %macro plot_one_group_iml(group_id); proc iml; N = 6; /* 每组6个点 */ point_mat = j(N, 2); /* 2列分别存x、y坐标 */ call randseed(&base_seed. + &group_id.); call randgen(point_mat, 'Uniform'); /* 直接把IML矩阵输出为SAS数据集,省去宏变量传值的格式问题 */ create point_set_&group_id. from point_mat[colname={'x','y'}]; append from point_mat; close point_set_&group_id.; quit; proc sgplot data=point_set_&group_id. noautolegend; title "第&group_id.组随机点散点图(IML生成)"; scatter x=x y=y; run; %mend; data _null_; do i = 1 to 20; call execute('%nrstr(%plot_one_group_iml('||i||'))'); end; run;
关键修正点说明
- 用
%nrstr包裹call execute中的宏调用,让每组的「生成数据→绘图」逻辑作为一个整体排队执行,不会被拆分成先跑所有生成步骤、再跑所有绘图步骤 - 每组数据集加组号后缀,避免多步执行时数据集互相覆盖
- 每组随机数流使用独立偏移的种子,保证各组随机值完全独立
- IML逻辑直接输出数据集,摒弃原来把矩阵值塞到datalines的易错写法,同时把随机数矩阵改成2列匹配x、y字段要求
内容的提问来源于stack exchange,提问作者bcg
相关产品推荐
相关产品推荐

