if-statement - 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;
解决方案
必须在一个数据步骤中处理多个帐户的可能性很高,因此您还需要一份BY AcccountId;
声明。LAG
语句不会在按组边界“重置”,因此当有多个帐户时,后续LAG
组的第一条记录将查看前一组的最后一条记录。
在内部,函数的每次使用都会在编码点LAG
创建一个隐式in-line
堆栈,并且很少会在条件DO
块中使用。 LAG
只会在流控制到达时堆叠——逻辑表达式LAG
中的 aif ... and ...
是可以的,因为SAS 总是完全评估C
逻辑表达式的所有部分(没有像 in或其他语言那样的捷径评估)
最可能的问题点是
if … and … and lag(DETALHE) = '...' then …
我认为不在数据集中,而是在数据步骤中DETALHE
计算。在被滞后引用的代码点,它的所有先前分配都是有条件的,因此可能会丢失(在数据步骤的顶部会隐式重置为丢失)。SET
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
作为组键的情况(而不是 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;
推荐阅读
- html - h1 标记中的文本溢出 div 容器
- linux - cx_Oracle 5.3 是否与 Oracle 客户端 19.10 兼容?
- javascript - 如何在 Angular 9 中使用 npm 包的 Highchart 地图集合的 CDN?
- javascript - 错误:使用了无效函数返回值
- reactjs - 无法在代码中找到问题以根据 React 中的用户输入动态分配组件名称
- angular - Syncfusion TreeGrid + Angular 11“错误:必须从注入上下文中调用注入()”
- php - Laravel 如何在两个独立的数据库中创建迁移关系?
- python - 在python中提取Unicode文本
- module - 如何在 Ejabberd 的自定义模块中加载模块?
- grep - devnagari unicode 文本的正确区域设置