Sas 跨多个数据步骤维护ID值

Sas 跨多个数据步骤维护ID值,sas,Sas,我已经创建了很多不同的数据集,但是我需要创建一个变量ID,它将在每行的第一个数据集中增加1。在下一个数据集中,我需要让ID变量从上一个数据步骤的ID变量停止的地方继续 我尝试过使用宏变量和retain语句,但不起作用。我正在使用的数据集将发生变化,因此我不能只是手动进入并将第二个数据集设置为数字#40,而另一个数据集没有设置。以下是我迄今为止所做工作的一个例子: %let test_id=1; data work.ex1; set work.ex1_test; ID + &am

我已经创建了很多不同的数据集,但是我需要创建一个变量ID,它将在每行的第一个数据集中增加1。在下一个数据集中,我需要让ID变量从上一个数据步骤的ID变量停止的地方继续

我尝试过使用宏变量和retain语句,但不起作用。我正在使用的数据集将发生变化,因此我不能只是手动进入并将第二个数据集设置为数字#40,而另一个数据集没有设置。以下是我迄今为止所做工作的一个例子:

%let test_id=1;

data work.ex1;
    set work.ex1_test;
    ID + &test_id.;
    retain ID 0;
    call symput('test_id', &test_id.+1);
    first_name= First;
run;

data work.ex2;
    set work.ex2_test;
    ID + &test_id.;
    retain ID length(&test_id.);
    call symput('test_id', &test_id.+1);
run;

也许这不是最优雅的解决方案,但有一种方法可能是:

1) 对每个原始数据集进行标记,即:

data work.ex1;
    set work.ex1;
    mark = 1;
run;

data work.ex2;
    set work.ex2;
    mark = 1;
run;
等等

2) 然后将所有数据集附加到一起并创建id变量:

data work.all_sets;
    set work.ex1 work.ex2 ...;
    id = _n_;
run;

3) 最后,使用标记再次分离数据集,以了解每行来自哪个数据集。

您已经接近了,但还不太清楚

您需要初始化宏变量的
ID
。然后增加它。然后将宏变量设置为新值
ID

%let initial_id=0;

data work.ex1;
    set sashelp.class;
    retain ID &initial_id.;
    ID+1;
    call symputx('initial_id', ID);
    first_name= name;
run;

data work.ex2;
    set sashelp.class;
    retain ID &initial_id.;
    ID+1;
    call symputx('initial_id',ID);
run;

首先,我认为当您使用:
ID+&test\u ID保留ID 0

也许这会起作用。在set语句中使用end=选项:

work.ex1 end=final;
然后在数据步骤的代码底部添加:

If final then do ;
id_next=id+1;
call symput('test_id',id_next);
end;
drop id_next;
然后从下一数据步骤中停止的地方开始,使用:

retain id &test_id ;

目的。你这么做的目的是什么?创建ID变量的目的是什么?如果ID的唯一目的是通过寻址源表名称来识别最终结果的源,那么SAS具有您可以利用的内置功能。以下代码是使用数据步骤选项“INDSNAME=”的示例。第一部分只是组成一些示例表,第二部分是使用此选项来确定obs的来源。这是相当直接的,所以我没有做在线评论

data class1 class2 class3;
    set sashelp.class;

    if age >14 then
        output class1;

    if sex='M' then
        output class2;
    else output class3;
run;

data test;
    set class: indsname=dsn;
    dsname=dsn;
run;

您可以使用数据集来存储最后使用的id,而不是宏变量。如果将此数据集设置为永久数据集,则它将跨会话工作

data lastid ;
  id=0;
run;

data a b ;
  do x=1 to 5; output; end;
run;

data new_a lastid (keep=id);
   if _n_=1 then set lastid ;
   if eof then output lastid ;
   set A end=EOF ;
   ID + 1 ;
   output new_a;
run;

data new_b lastid (keep=id);
   if _n_=1 then set lastid ;
   if eof then output lastid ;
   set b end=EOF ;
   ID + 1 ;
   output new_b;
run;

我不能说我理解
mark
的目的是什么,以及您实现它的方式。您是指第二个数据集中的
mark=2
?不管怎样,我都不认为这是一种有效的方法;以另一种方式从早期数据集中获取rowcount值比将它们一起设置更容易。是的,我的意思是mark=2。您的解决方案仍然更好。
retainid0
不会重新设置ID。retain不是可执行语句,因此
0
只是在编译时初始化它;它大致相当于
如果_n_=1,那么ID=0除非它甚至在
集合
被处理之前就出现了(尽管如果set语句上有
ID
它也不相关)。否则我喜欢这里的一些概念。虽然所使用的方法I(和OP)更简单、更短,但这种方法很好,因为它清楚地说明了在数据步骤结束时会发生什么,因此从组织的角度来看,这种方法更好。如果数据步骤正在做很多不同的事情,那么这种方法更清晰,因此更好。感谢对retain语句的澄清。不确定。从性能的角度来看,这也更好-对于非常大的数据集,对每一行执行
调用symput
,而不仅仅是最后一行,可能会产生明显的影响。从最初的问题来看,这并不是非常清楚(尽管我之前编辑了它,试图让它更清楚)但我认为用户希望每一行的ID值,而不是每一个表的ID值。