sas - 在 SAS 宏中执行循环
问题描述
我正在尝试创建一个将遍历列的字符串值的宏。
这是数据:
SUBJECT VISIT PARAMETER
001 Baseline param1
001 Visit 2 param1
001 Visit 3 param1
001 Baseline param2
001 Visit 2 param2
001 Visit 3 param2
002 Baseline param1
002 Visit 2 param1
002 Visit 3 param1
002 Baseline param2
002 Visit 2 param2
002 Visit 3 param2
这是我现在拥有的宏:
%macro want(numb, string);
DATA want&numb;
SET have;
IF parameter = &string;
RUN;
%mend want;
在其当前形式中,我必须在 PARAMETER 列中输入数字和字符串值。我想修改宏,以便可以迭代 30 个参数而不是以下参数:
%want(1, 'param1');
%want(2, 'param2');
...
%want(30, 'param30');
任何见解将不胜感激。
解决方案
如果您想将多个值传递给宏调用,那么通常最容易使用分隔列表。如果需要,宏可以使用%SCAN()
宏功能来选择单个值。您可以使用该COUNTW()
函数来确定值的数量。将其包装在%SYSFUNC()
宏函数中以在宏逻辑中使用它。
由于您想在 SAS 代码中将值用作字符串文字,因此最简单的方法是要求用户在他们传递的值中包含引号。与在 SAS 语句中写入值时相同。
当您像这样一次拥有所有值时,您可以使用一个数据步骤在输入数据的一次传递中写入所有输出数据集。
%macro split(inds,prefix,values);
%local i n dsname sep;
%let n=%sysfunc(countw(&values,%str( ),q));
data
%do i=1 %do &n;
%let dsname=&prefix.&n;
&dsname.
%end;
;
set &inds ;
%do i=1 %to &n;
%let dsname=&prefix.&n;
&sep. if parameter = %scan(&values,&i,q) then output &dsname.;
%let sep=else;
%end;
run;
%mend ;
那么您的示例将是这样的调用:
%split(inds=have,prefix=want,values='param1' 'param2' ... 'param30')
如果您有一个包含值列表的数据集,则可以使用简单的 SQL 查询来构建值列表。像这样:
proc sql noprint;
select distinct quote(trim(param),"'") into :parmlist separated by ' '
from list_of_parameters
;
quit;
并在调用中使用该宏变量。
%split(inds=have,prefix=want,values=&parmlist.)
如果您希望生成的数据集数量仅基于出现在 HAVE 中的 PARAMETER 的值,那么您可以将该逻辑移至宏本身,并使宏的用户更容易使用。
请注意,通常不需要像这样拆分数据集。如果您想使用原始数据集 HAVE 但仅对特定 PARAMETER 值使用观察结果,则只需使用 WHERE 语句或 WHERE= dataset 选项。
推荐阅读
- c++ - GCC中优先级队列的奇怪shared_ptr比较器选择
- mongodb - Mongo 聚合 - 如何用某些函数包装表达式值?
- java - TextView中的文字无法正常显示:出现空白
- c++ - C++ 使用 cin 给变量一个非整数的值
- mysql - 数组中的 json_contains 返回空集
- vba - 尝试使用 excel VBA 访问网站上的数据,我需要能够单击按钮
- python-2.7 - Paramiko 在遇到缺少输出时挂起
- sql - 当到期日总是在每个月的最后一天时,查找不同的 ID
- c# - 如何在服务器端防止href属性的xss?
- android - Android 上的 Tensorflow 推理,找不到“迭代器”操作。没有注册 OpKernel 来支持 Op