该代码的目标是将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;
答案 0 :(得分:2)
在一个数据步骤中处理多个帐户的可能性很高,因此,您还需要一个BY AcccountId;
语句。 LAG
语句不会按组边界“重置”,因此,当有多个帐户时,连续组第一条记录中的LAG
将查看前一组的最后一条记录
内部每次使用LAG
函数都会在编码时创建一个隐式in-line
堆栈,并且很少在有条件的DO
块内使用。 LAG
仅在流控制到达时才堆叠-LAG
逻辑表达式中的if ... and ...
是可以的,因为 SAS始终完全评估逻辑表达式的所有部分(没有像C
或其他语言那样的捷径评估)
最可能出现的问题是
if … and … and lag(DETALHE) = '...' then …
我假设DETALHE
在SET
数据集中是 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;