SAS:在if语句中删除列

时间:2013-09-25 21:51:42

标签: sas

我有一个名为have的数据集,其中一个条目包含多个变量,如下所示:

message reference time  qty  price 
x       101       35000 100  .

上述数据集每次都在message可以=“A”的循环中发生变化。如果message =“X”,那么这意味着从MASTER集中删除100个数量,其中reference数字等于MASTER数据库中的reference数字。 price =。是因为它已经在reference = 101下的MASTER数据库中。 MASTER数据库以某种价格汇总所有可用订单和可用数量。如果在下一个循环message =“A”中,那么have数据集将如下所示:

消息参考时间数量价格     A 102 35010 150 500

那么这意味着要向MASTER数据库添加一个新的reference号码。换句话说,到append到MASTER的行。

我的循环中有以下代码,当有message X时更新MASTER数据库中的数量:

data b.master;
modify b.master have(where=(message="X")) updatemode=nomissingcheck;
by order_reference_number;
if _iorc_ = %sysrc(_SOK) then do;
replace;
end;
else if _iorc_ = %sysrc(_DSENMR) then do;
      output;
      _error_ = 0;
    end;
else if _iorc_ = %sysrc(_DSEMTR) then do;
      _error_ = 0;
end;
else if _iorc_ = %sysrc(_DSENOM) then do;
_error_ = 0;
end;
run;

我使用replace更新数量。但是因为我的price =。当message为X时,上述代码会设置price ='。'通过reference语句在MASTER中replace = 101 ...我不想要。因此,我更愿意删除message数据集中的价格列have = X.但是我不想在message = A时删除列价,因为我使用此代码

proc append base=MASTER data=have(where=(msg_type="A")) force;
run;

因此,我的代码价格为Modify声明:

data have(drop=price_alt); 
set have; if message="X" then do; 
output;end; 
else do; /*I WANT TO MAKE NO CHANGE*/ 
end;run;

但它没有做我想要的。如果消息不等于X,那么我不想删除列。如果它等于X,我想删除列。如何调整上面的代码才能使其正常工作?

2 个答案:

答案 0 :(得分:3)

试试这个:

data outX(drop=price_alt) outNoX;
set have;
if message = "X" then
   output outX;
else
   output outNoX;
run;

正如@sasfrog在评论中所说的那样,一个表要么有列,要么没有。如果你想要MESSAGE =“X”的子集,那么你可以使用这样的东西来创建2个数据集。

答案 1 :(得分:3)

诚实地说这是一个奇怪的要求,这样就会提出一个问题,即你所做的是最好的做法。但是,本着回答这个问题的精神......

DomPazz的答案提供了将数据拆分为两个可能的集合的选项,但如果您希望代码中的代码始终引用特定的数据集,则会产生其自身的复杂性。

在一个数据步骤中,您也不能告诉SAS输出到“相同”数据集,其中一个实例具有列而一个实例没有。因此,您希望代码本身是动态的,因此存在的数据步骤可以是删除列的数据步骤,也可以是不删除列的数据步骤,具体取决于message = x。对此动态代码的回答与SAS中的许多内容一样,解决了宏的创造性使用问题。它看起来像这样:

/* Just making your input data set */

data have;
message='x';
time=35000;
qty=1000;
price=10.05;
price_alt=10.6;
run;

/* Writing the macro */

%macro solution;
    %local id rc1 rc2;

    %let id=%sysfunc(open(work.have));
    %syscall set(id);
    %let rc1=%sysfunc(fetchobs(&id, 1));
    %let rc2=%sysfunc(close(&id));

%IF &message=x %THEN %DO;
    data have(drop=price_alt);
    set have;
    run;
%END;

%ELSE %DO;
    data have;
    set have;
    run;
%END;
%mend solution;

/* Running the macro */

%solution;