IF-THEN和LAG(函数)语句存在问题-无法正确分类

时间:2019-06-18 02:32:08

标签: if-statement sas

晚上好。我在用几个IF THEN DO语句以及LAG函数构建代码时遇到问题。我正在使用SAS企业指南工具和SQL编码。

该代码的目标是将ATM上的存款分为“已记录存款”,“自己帐户中的存款”和“未记录存款”

分类发生在DETALHE列中。

CHAVE = lag(CHAVE)并且在登录后有一笔存款(DES_TRANS列)时,我们有一个“在自己的帐户中存款”。

CHAVE不等于lag(CHAVE)时,我们需要看一下“ TEMPO”列,即“ TIME”。如果TIME小于200秒(表示超时),则我们有“已记录的存款”。如果大于200秒,则为“未记录的存款”。

问题是当我们有大量存款时,我们需要使用按首个IF-THEN语句分类的值(我为此使用LAG(DETALHE))。

首先,代码未对所有行进行分类。 例如第287和288行。

我用RETAIN语句解决了这个问题。 现在,只是没有提供正确的输出

我希望第490行的输出为'DepósitoNão-Logado'。

FORMAT DETALHE $CHAR50.;

RETAIN DETALHE;



IF DES_TRANS ne 'Depósito' THEN DO DETALHE = ' '; END;



IF (DES_TRANS = 'Depósito' AND lag(DES_TRANS) = 'Login' AND CHAVE = lag(CHAVE)) THEN DO DETALHE = 'Depósito na Própria Conta';END;



IF (DES_TRANS = 'Depósito' AND lag(DES_TRANS) = 'Login' AND CHAVE ne lag(CHAVE) AND TEMPO <=200) THEN DO DETALHE = 'Depósito Logado';END;

IF (DES_TRANS = 'Depósito' AND lag(DES_TRANS) = 'Login' AND CHAVE ne lag(CHAVE) AND TEMPO >=200) THEN DO DETALHE = 'Depósito Não-Logado';END;


IF (DES_TRANS = 'Depósito' AND lag(DES_TRANS) = 'Depósito' AND lag(DETALHE) = 'Depósito Não-Logado') THEN DO DETALHE = 'Depósito Não-Logado';END;



IF (DES_TRANS = 'Depósito' AND lag(DES_TRANS) = 'Depósito' AND lag(DETALHE) = 'Depósito na Própria Conta' AND CHAVE = lag(CHAVE)) THEN DO DETALHE = 'Depósito na Própria Conta';END;

IF (DES_TRANS = 'Depósito' AND lag(DES_TRANS) = 'Depósito' AND lag(DETALHE) = 'Depósito na Própria Conta' AND CHAVE ne lag(CHAVE) AND TEMPO <=200) THEN DO DETALHE = 'Depósito Logado';END;

IF (DES_TRANS = 'Depósito' AND lag(DES_TRANS) = 'Depósito' AND lag(DETALHE) = 'Depósito na Própria Conta' AND CHAVE ne lag(CHAVE) AND TEMPO >=200) THEN DO DETALHE = 'Depósito Não-Logado';END;



IF (DES_TRANS = 'Depósito' AND lag(DES_TRANS) = 'Depósito' AND lag(DETALHE) = 'Depósito Logado' AND TEMPO <=200) THEN DO DETALHE = 'Depósito Logado';END;

IF (DES_TRANS = 'Depósito' AND lag(DES_TRANS) = 'Depósito' AND lag(DETALHE) = 'Depósito Logado' AND TEMPO >=200) THEN DO DETALHE = 'Depósito Não-Logado';END;



RUN;

1 个答案:

答案 0 :(得分:2)

在一个数据步骤中处理多个帐户的可能性很高,因此,您还需要一个BY AcccountId;语句。 LAG语句不会按组边界“重置”,因此,当有多个帐户时,连续组第一条记录中的LAG将查看前一组的最后一条记录

内部每次使用LAG函数都会在编码时创建一个隐式in-line堆栈,并且很少在有条件的DO块内使用。 LAG仅在流控制到达时才堆叠-LAG逻辑表达式中的if ... and ...是可以的,因为 SAS始终完全评估逻辑表达式的所有部分(没有像C或其他语言那样的捷径评估)

最可能出现的问题是

if … and … and lag(DETALHE) = '...' then … 

我假设DETALHESET数据集中是 NOT ,并且正在数据步骤中进行计算。在DETLAHE的代码点被滞后引用时,它的所有先前赋值都是有条件的,因此可能会丢失(因为DETALHE将隐式地重置为在数据步骤的顶部丢失)

对于涉及滞后值的非平凡编码,我的个人风格是将每个变量置于其自己的工作变量中。当清楚地表明了状态贡献角色时,该算法可以更易于理解,并且不容易编写错误的状态分类。

对于希望在计算值之前的滞后值来计算值的情况,您确实需要RETAIN保存该先前计算值的变量。

出于分类目的,边界条件应有不同的规则。

* state at 200 is fast only because fast classification done last;
if X <= 200 then state='slow';
if X >= 200 then state=`fast';

* better rule;
if X <  200 then state='slow'; * exclusively < 200; 

对于CHAVE是组密钥(而不是假定的AccountId)的情况,代码可以简化一些。嵌套逻辑(而不是一系列语句)将帮助覆盖有助于计算DETALHE分类的所有组合因素-如果它们完全覆盖组合空间及其逻辑值,则一系列不相交的IF / THEN是可以的不要重叠(完全不同)。表示复杂性,一致性和完整性之间平衡的代码是问题。

… 
   SET … 
   BY AccountId;
… 

prior_DES_TRANS = lag(DES_TRANS);
prior_CHAVE = lag(CHAVE);
prior_CLASSIFICATION = lag(CLASSIFICATION);

length DETALHE prior_DETALHE $30;
retain prior_DETALHE;

if first.AccountID then do; /* do not lag into prior group */
  prior_DES_TRANS = ' ';
  prior_CHAVE = ' ';
  prior_CLASSIFICATION = ' ';
  prior_DETALHE = ' ';
end;

if DES_TRANS = 'Depósito' then do;
  sequenceLoginDeposit = prior_DES_TRANS = 'Login';
  sequenceDepositDeposit = prior_DES_TRANS = 'Depósito';
end;    

sameCHAVE = CHAVE = prior_CHAVE;

* use nested logic to prevent missing some combination of factors that 
* contribute to DETALHE classification;

if sequenceLoginDeposit then do;
  if sequenceLoginDeposit then do;
    if sameCHAVE then 
      DETALHE = 'Depósito na Própria Conta';
    else /* not sameCHAVE */
    if TEMPO < 200 THEN
      DETALHE = 'Depósito Logado';
    else /* tempo >= 200 */
      DETALHE = 'Depósito Não-Logado';
  end;
  else do;
  end;
end;
else
if sequenceDepositDeposit then do;
  if prior_DETALHE = 'Depósito Não-Logado' then
    DETALHE = 'Depósito Não-Logado';
  else 
  IF prior_DETALHE = 'Depósito na Própria Conta' then do;
    if sameCHAVE THEN 
      DETALHE = 'Depósito na Própria Conta';
    else /* not sameCHAVE */
    IF TEMPO < 200 THEN 
      DETALHE = 'Depósito Logado';
    ELSE /* and TEMPO >=200 */
      DETALHE = 'Depósito Não-Logado';
  end;
  else
  IF prior_DETALHE = 'Depósito Logado' then do;

    /* is sameCHAVE important here ? */

    if TEMPO < 200 THEN
      DETALHE = 'Depósito Logado';
    else
      DETALHE = 'Depósito Não-Logado';
  end;
  ELSE
    DETALHE = 'unhandled';
end;

prior_DETALHE = DETALHE;