数据步骤中的宏变量
Macro variables inside data step
我需要在宏的数据步骤中保存某个变量的值,然后在同一数据步骤中使用该宏。我尝试使用 SYMPUT
,但如果我理解正确的话,以这种方式创建的宏变量不能在同一数据步骤中使用(我猜它是在数据步骤结束时分配的,我猜?)
这是一个简化的例子。我有一个数据字段列表 t1,...,t100
表示在特定时间发生的事情,事件用数字表示,还有一个数据字段 t_start
给出了我对每个过程感兴趣的过程的开始时间观察。我想检查我是否拥有所有数据,否则就放弃观察。我想进行如下操作。
DATA WANT;
SET HAVE;
CALL SYMPUT('START_TIME', t_start);
DO I=&START_TIME. TO 100;
IF t_&I. = . THEN DELETE;
END;
RUN;
这行不通,我认为是出于上述原因。有解决方法吗?
备注:
- 我简化了情况,我看到的实际情况更复杂(例如,变量不叫
t1,...t100
,而是结构更复杂的东西)。如果可能的话,我希望尽可能接近我上面给出的方法,因为不同的解决方案可能不适用于我的情况。当然,如果这是不可能的,那么欢迎任何解决方案!
- 我试着查看
RESOLVE
,但它似乎并没有满足我的要求(或者至少我对它的理解还不够深入,无法让它满足我的需求)。
- 作为最后的手段,我可以尝试使用两个数据步骤来解决问题,一个定义宏变量,另一个使用它来检查和删除不需要的观察值。如果可能的话,我宁愿避免这种解决方案。
更新:我按照解决方案中的建议使用数组解决了这个问题。
这可能是使用数组的更好方法。
考虑到您 post 编辑的内容,这行得通。如果它不符合您的需要,请 post 详细说明您的情况。
data demo;
array t(10);
do row=1 to 100;
do i=1 to 10;
t(i)=rand('integer', 1, 5);
end;
start = rand('integer', 1, 10);
output;
end;
run;
data test;
set demo;
array t(10);
do i=start to dim(t);
if t(i) < 2 then do;
delete;
leave;*exits loop;
end;
end;
run;
当数据步长为 运行 时,该步长为 'compiled' 且所有与号 (&
) 宏变量分辨率均已解析。 运行 已编译步骤无法更改其源代码。
如果您提交了两次代码,第一次会记录 WARNING: Apparent symbolic reference not resolved.
第二次不会有警告,并且会使用从 prior投稿.
假设您的数据记录有很多变量,以及两个标记变量,其值是变量的名称,标记某些处理的开始和停止。虽然数据结构笨重,但您可以使用数组来调解对要处理的变体变量集的访问。
例如:
data have;
input
a b c d e f g h start $ stop $ ; datalines;
1 2 3 4 5 6 7 8 d e
11 12 13 14 15 16 17 18 a b
0 1 1 2 3 5 8 11 c h
1 1 1 1 1 . 1 1 a e wont be deleted because . is at f
1 2 3 4 . 6 7 8 a h
run;
data want;
set have;
array num a--h;
do i = 1 to dim(num);
if vname(num(i)) = start then startindex=i;
if vname(num(i)) = stop then stopindex=i;
end;
do i = min(startindex,stopindex) to max(startindex,stopindex);
if missing(num(i)) then delete;
end;
run;
您正在尝试使用 dataset
变量 t_start
和 i
的值来确定要测试的变量。这就是数组的用途。
DATA WANT;
SET HAVE;
array t t1-t100;
DO I=t_start TO 100;
IF t(i) = . THEN DELETE;
END;
RUN;
不需要宏变量,更不用说可以在时间上倒退并在数据步骤已经开始后修改代码的宏变量了运行。
我需要在宏的数据步骤中保存某个变量的值,然后在同一数据步骤中使用该宏。我尝试使用 SYMPUT
,但如果我理解正确的话,以这种方式创建的宏变量不能在同一数据步骤中使用(我猜它是在数据步骤结束时分配的,我猜?)
这是一个简化的例子。我有一个数据字段列表 t1,...,t100
表示在特定时间发生的事情,事件用数字表示,还有一个数据字段 t_start
给出了我对每个过程感兴趣的过程的开始时间观察。我想检查我是否拥有所有数据,否则就放弃观察。我想进行如下操作。
DATA WANT;
SET HAVE;
CALL SYMPUT('START_TIME', t_start);
DO I=&START_TIME. TO 100;
IF t_&I. = . THEN DELETE;
END;
RUN;
这行不通,我认为是出于上述原因。有解决方法吗?
备注:
- 我简化了情况,我看到的实际情况更复杂(例如,变量不叫
t1,...t100
,而是结构更复杂的东西)。如果可能的话,我希望尽可能接近我上面给出的方法,因为不同的解决方案可能不适用于我的情况。当然,如果这是不可能的,那么欢迎任何解决方案! - 我试着查看
RESOLVE
,但它似乎并没有满足我的要求(或者至少我对它的理解还不够深入,无法让它满足我的需求)。 - 作为最后的手段,我可以尝试使用两个数据步骤来解决问题,一个定义宏变量,另一个使用它来检查和删除不需要的观察值。如果可能的话,我宁愿避免这种解决方案。
更新:我按照解决方案中的建议使用数组解决了这个问题。
这可能是使用数组的更好方法。 考虑到您 post 编辑的内容,这行得通。如果它不符合您的需要,请 post 详细说明您的情况。
data demo;
array t(10);
do row=1 to 100;
do i=1 to 10;
t(i)=rand('integer', 1, 5);
end;
start = rand('integer', 1, 10);
output;
end;
run;
data test;
set demo;
array t(10);
do i=start to dim(t);
if t(i) < 2 then do;
delete;
leave;*exits loop;
end;
end;
run;
当数据步长为 运行 时,该步长为 'compiled' 且所有与号 (&
) 宏变量分辨率均已解析。 运行 已编译步骤无法更改其源代码。
如果您提交了两次代码,第一次会记录 WARNING: Apparent symbolic reference not resolved.
第二次不会有警告,并且会使用从 prior投稿.
假设您的数据记录有很多变量,以及两个标记变量,其值是变量的名称,标记某些处理的开始和停止。虽然数据结构笨重,但您可以使用数组来调解对要处理的变体变量集的访问。
例如:
data have;
input
a b c d e f g h start $ stop $ ; datalines;
1 2 3 4 5 6 7 8 d e
11 12 13 14 15 16 17 18 a b
0 1 1 2 3 5 8 11 c h
1 1 1 1 1 . 1 1 a e wont be deleted because . is at f
1 2 3 4 . 6 7 8 a h
run;
data want;
set have;
array num a--h;
do i = 1 to dim(num);
if vname(num(i)) = start then startindex=i;
if vname(num(i)) = stop then stopindex=i;
end;
do i = min(startindex,stopindex) to max(startindex,stopindex);
if missing(num(i)) then delete;
end;
run;
您正在尝试使用 dataset
变量 t_start
和 i
的值来确定要测试的变量。这就是数组的用途。
DATA WANT;
SET HAVE;
array t t1-t100;
DO I=t_start TO 100;
IF t(i) = . THEN DELETE;
END;
RUN;
不需要宏变量,更不用说可以在时间上倒退并在数据步骤已经开始后修改代码的宏变量了运行。