首页 > 解决方案 > IF-THEN 和 LAG(函数)语句的问题 - 未正确分类

问题描述

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

该代码的目标是将在 ATM 中进行的存款分类为“记录存款”、“自己账户中的存款”和“非记录存款”

分类出现在 DETALHE 列中。

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

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

问题是当我们有连续存款时,我们需要使用由第一个 IF-THEN 语句分类的值(我正在使用LAG(DETALHE)它)。

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

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

我希望第 490 行的输出是“Depósito Nã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;

标签: if-statementsas

解决方案


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

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

最可能的问题点是

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

我认为不在数据集中,而是在数据步骤中DETALHE计算。在被滞后引用的代码点,它的所有先前分配都是有条件的,因此可能会丢失(在数据步骤的顶部会隐式重置为丢失)。SETDETLAHEDETALHE

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

对于在计算值之前想要计算值的滞后值的情况,您确实需要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作为组键的情况(而不是 presumed 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;

推荐阅读