迭代行问题你好,
我非常感谢之前的所有回复,并且每天都在了解越来越多的关于 JSL 的知识。 至此,我已经掌握了基础知识,并且了解了为了循环,对于每一行和使用公式功能。 这非常有帮助。 正如我在上一篇文章中提到的,我正在处理一个数据集,并且有 4 个关键列:
1) PATIENTID:患者编号的唯一值列表
2) VALUE:特定时间点患者评分的值
3) 时间:收集患者评分的时间点
4) PARAM:患者评分由 4 个单独项目和总分组成(ITEM1、ITEM2、ITEM3、ITEM4 和 TOTAL)。 总分就是ITEM1+ITEM2+ITEM3+ITEM4的总和。
由此,我想创建第五列(称为“测试”)。 TEST 的值基于以下逻辑:
对于个别患者来说,如果基线值为:
- 总计 > 9 或
- ITEM1、ITEM2、ITEM3 或 ITEM4 中的 1 个 > 3 或
- ITEM1、ITEM2、ITEM3 或 ITEM4 中的 3 个 > 2
那么“TEST”中的相应行应被评估为“YES”。 非基线值和其他值应评估为“NO”。 该逻辑应该迭代到每个患者和数据表中的每一行。
我在迭代数据集中的行时遇到问题。 原因是每个患者填写量表的时间点数量不同。 有些患者很早就退出了。 由于每个患者的行数不同,我很难弄清楚如何迭代行来编写脚本。
我尝试组合一些 IF 语句,但陷入需要迭代到下一个患者 ID 的位置。 我附上了我写的脚本,但卡住了。 任何帮助是极大的赞赏。
Names Default To Here( 1 );
dt = current data table ();
dt << New Column ("TEST", Character, Formula(
If(:TIME == "BASELINE",
theRow = Row();
thePatient = :PATIENTID;
If(:PARAM == "TOTAL",
If(N Rows(dt << Get Rows Where(
Row()>=theRow &
thePatient == :PATIENTID &
:VALUE > 9
)
) > 0
,"YES"
,"NO"
)))
));这是数据表的示例(出于隐私考虑,对真实患者信息进行了编辑)

回复:迭代行问题谢谢,现在完全有道理了。 感谢您花时间解释,非常有帮助!
回复:迭代行问题@SrihariGopal ,
您的第一篇文章介绍了公式和 Set Each Value() 如何迭代行。因此,请记住以下几条信息:
- 逻辑语句被评估为 True 或 False。 True 相当于 1,False 相当于 0
- 假设 x 是一个数值。 JSL 函数 If( x, "YES", "NO" ) 查看 x 的值。 如果 x > 0,则结果为 True(1)=>YES,否则为 False(0)=>NO。
- :TIME == "BASELINE" 是一个返回 1 或 0 的逻辑语句,因此乘法函数将起作用,而不是使用“AND”(&)。 换句话说,TIME 必须等于 BASELINE,并且其中一条规则必须为真,即 1*1 = 1。 如果其中一个为假,则结果为零或为假。
- 外部 Maximum() 函数有 3 个参数,即 3 个规则。 该最大值函数取代了“OR”(|)。 如果 3 个规则全部为 false,则外部最大值返回 0。 如果 3 个规则中的任何一个返回 1 (True),则最大值返回 1。 但请记住,此结果具有逻辑乘数,因此这只适用于 BASELINE 值。
- 关于规则:规则 #1 ( :TOTAL > 9 ) 返回 1 或 0。规则 #2 查找 4 项中的最大值,如果大于 3,则至少有一项大于 3。 规则 #3 是 4 个逻辑结果的总和(项目 1 >2 等)。如果该总和大于 2,则其中 3 或 4 个项目大于 2。
对逻辑语句使用算术可以更轻松、更快速地找到满足“k of n”规则的案例。 还有其他方法,例如连接 4 个 ITEM 并检查它们是否在 {“0111”、“1011”、“1101”、“1110”} 中,或者将它们设为数字并查找这些值。但总和只需要一张支票(>2)。由于我对规则 #3 使用算术,所以我使用数学函数 Maximum() 而不是 OR,并用乘法而不是 AND 来处理剩余的逻辑。请注意,您可以使用将逻辑函数与数学函数混合的语句。
希望有帮助。
回复:迭代行问题太感谢了! 这非常有效。
我正在阅读剧本,我想知道你是否可以再解释一下。 MAXIMUM 函数在这种情况下如何工作? 我了解您最多正在寻找 3 条规则。 但是我看到 * 运算符,我认为它意味着乘法。 我对乘法与 MAXIMUM 函数如何在 IF 语句中一起工作感到困惑。
非常感谢!回复:迭代行问题@SrihariGopal ,
你说过你的目标是
对于个别患者来说,如果基线值为:
- 总计 > 9 或
- ITEM1、ITEM2、ITEM3 或 ITEM4 中的 1 个 > 3 或
- ITEM1、ITEM2、ITEM3 或 ITEM4 中的 3 个 > 2
那么“TEST”中的相应行应被评估为“YES”。 非基线值和其他值应评估为“NO”。 该逻辑应该迭代到每个患者和数据表中的每一行。
可以在堆叠表中完成复杂的规则,但它们会变得混乱。 如果表按照 PATIENTID 和 TIME 进行堆叠,其中规则由 PARAM 应用,则管理起来会容易得多。 如果表非常大,此方法可能效率不高。
附件是您的示例表,其中包含两个附加 PATIENTID,用于测试这 3 条规则。在使用附加脚本之前,您应该检查公式是否充分捕获了您的 3 条规则。 我添加了评论栏和颜色以方便检查。

拆分后,以下是三个规则 TEST 列的公式。 该脚本还包括用于取消堆叠和重新组织表的 JSL 代码。
dt_split:TEST << Set Each Value(
If(
(:TIME == "BASELINE") *
Maximum(
:TOTAL > 9, //rule 1
Maximum( :ITEM1, :ITEM2, :ITEM3, :ITEM4 ) > 3, //rule 2
(:ITEM1 > 2) + (:ITEM2 > 2) + (:ITEM3 > 2) + (:ITEM4 > 2) >= 3 //rule 3
),
"YES",
"NO"
));
。