【问题标题】:Dealing with conditionals in a better manner than deeply nested ifelse blocks以比深度嵌套的 ifelse 块更好的方式处理条件
【发布时间】:2013-08-09 15:09:00
【问题描述】:

我正在尝试编写一些代码来分析我公司的保险计划产品...但它们很复杂! PPO 计划很简单,但高免赔额健康计划很复杂,因为他们为家庭计划引入了“拆分”自付额自付最高限额(个人和总计)。它的工作原理是这样的:

  • 一旦个人达到个人免赔额,他/她将获得 90% 的保障
  • 一旦计划中剩余的 1+ 个人达到总免赔额,整个家庭的承保率为 90%
  • 个人不能仅凭医疗费用满足家庭免赔额

我想为我的家庭成员(有四个)输入一个费用向量,并输出每个计划的总成本。下表列出了可能的情况,并带有以下列代码:

  • ded_ind: 有个人达到个人免赔额吗?
  • ded_tot: 总免赔额达到了吗?
  • oop_ind: 个人自掏腰包达到最大值了吗
  • oop_tot:自付总额达到最大值了吗?
  • exp_ind = 最高消费者的支出
  • exp_rem = 其余/other/ 家庭成员的开支(不是最高支出者)
  • oop_max_ind = 个人支付的最高自付费用水平(当ded_ind + 0.1 * exp_ind = 个人自付费用最高时
  • oop_max_fam = 与个人相同,但仅针对其余家庭成员

桌子:

| ded_ind | oop_ind | ded_rem | oop_rem | formula                                       
|---------+---------+---------+---------+---------------------------------------------------------------------------|
|       0 |       0 |       0 |       0 | exp_ind + exp_rem                                                         |
|       1 |       0 |       0 |       0 | ded_ind + 0.1 * (exp_ind - ded_ind) + exp_rem                             |
|       0 |       0 |       1 |       0 | exp_ind + ded_rem + 0.1 * (exp_rem - ded_rem)                             |
|       1 |       1 |       0 |       0 | oop_max_ind + exp_fam                                                     |
|       1 |       0 |       1 |       0 | ded_ind + 0.1 * (exp_ind - ded_ind) + ded_rem + 0.1 * (exp_rem - ded_rem) |
|       0 |       0 |       1 |       1 | oop_max_rem + exp_ind                                                     |
|       1 |       0 |       1 |       1 | ded_ind + 0.1 * (exp_ind - ded_ind) + oop_max_rem                         |
|       1 |       1 |       1 |       0 | oop_ind_max + ded_rem + 0.1 * (exp_rem - ded_rem)                         |
|       1 |       1 |       1 |       1 | oop_ind_max + oop_rem_max                                                 |

省略: 0 1 0 00 0 0 10 1 1 00 1 0 1 不存在,因为如果 ded_indded_rem,分别没有遇到过。

我当前的代码有点像这样的 ifelse 循环(不是代码,而是它的作用):

check if plan is ppo or hsa
  if hsa plan
    if exp_ind + exp_rem < ded_rem # didn't meet family deductible
      if exp_ind < ded_ind # individual deductible also not met
        cost = exp_ind + exp_rem
      else is exp_ind > oop_ind_max # ded_ind met, is oop_ind?
        ded_ind + 0.1 * (exp_ind - ded_ind) + exp_fam # didn't reach oop_max_ind
        else oop_max_ind + exp_fam # reached oop_max_ind

    else ...

在else之后,总和大于家庭免赔额。我检查它是否由两个以上的人贡献,然后继续这样。

我的问题,既然我已经给出了问题的一些背景知识:有没有比ifelse 循环一次过滤它们更好的方法来管理这样的条件情况?

代码最终看起来是多余的,因为一个检查一些更高级别的条件(考虑满足或不满足ded_rem 的表......在这两种情况下仍然需要检查ded_indoop_max_ind ,并且代码是一样的……只是定位在ifelse结构中的两个不同的地方)。

这可以通过某种矩阵运算来完成吗?网上还有其他更聪明的方法来处理条件过滤的例子吗?

非常感谢您的任何建议。


附:我正在使用 R 并将创建与 shiny 的交互,以便其他员工可以输入每个家庭成员的最佳和最坏情况,并通过点或条形图查看哪个计划提前出现。

【问题讨论】:

  • 您刚刚提供了一个基于四个布尔值的状态表。合乎逻辑的方法是将它们视为 0 到 15 之间的二进制数。只需将它们映射到适当的函数即可。
  • 有趣!那么我只需要做四次检查:1)大于ded_ind,2)大于oop_ind_max,3)大于ded_rem和4)大于oop_rem_max,然后返回这四个值(0或 1) 并计算二进制等价物——这是要点吗?
  • 您可以粘贴条件值,然后使用分隔符并使用switch(val, v1=expr2, v2=expr2, v3=expr3, 'other')。如果您想要测试代码,请发布一个真实示例。

标签: r if-statement conditional


【解决方案1】:

由于这个问题不是很具体,这里有一个更简单的例子/答案:

# example data
test <- expand.grid(opt1=0:1,opt2=0:1)
# create a unique identifier to represent the binary variables
test$code <- with(allopts,paste(opt1,opt2,sep=""))
# create an input variable to be used in functions
test$var1 <- 1:4

#  opt1 opt2 code var1
#1    0    0   00    1
#2    1    0   10    2
#3    0    1   01    3
#4    1    1   11    4

根据二进制条件应用的各个函数,以及每个组合的预期结果:

var1 + 10    #code 00 - intended result =   11
var1 + 100   #code 10 - intended result =  102
var1 + 1000  #code 01 - intended result = 1003
var1 + var1  #code 11 - intended result =    8

使用ifelse 组合进行计算:

test$result <- with(test,
  ifelse(code == "00", var1 + 10,
  ifelse(code == "10", var1 + 100,
  ifelse(code == "01", var1 + 1000,
  ifelse(code == "11", var1 + var1,
  NA
)))))

结果:

  opt1 opt2 code var1 result
1    0    0   00    1     11
2    1    0   10    2    102
3    0    1   01    3   1003
4    1    1   11    4      8

【讨论】:

    【解决方案2】:

    根据结果转换为二进制值的建议给了我一个想法,这也帮助我了解到可以进行矢量化 TRUE / FALSE 检查(我想这对很多人来说可能很明显)。

    这是我目前的想法:

    expenses 将是个人预测当年医疗费用的向量(以三个人为例):

    expenses <- c(1500, 100, 400)
    

    我们将exp_ind设置为最大值,并将其余部分相加为exp_rem

    exp_ind <- max(expenses)
    
    # [1] index of which() for cases with multiple max values
    exp_rem <- sum(expenses[-which(expenses == exp_ind)[1]])
    

    对于任何给定的计划,我都可以设置一个带有截止点的向量,例如:

    • 个人免赔额 = 1000
    • 个人自付费用最高 = 2000(需要承担 11k 的费用才能到达那里)
    • 家庭免赔额 = 2000
    • 家庭自掏腰包最多 = 4000(需要承担 22k 的费用才能到达那里)

    设置这些值:

    ded_ind <- 1000
    oop_max_ind <- 11000
    ded_tot <- 2000
    oop_max_tot <- 22000
    
    cutoffs <- c(ded_ind, oop_max_ind, ded_tot, oop_max_tot)
    

    现在我们可以对照截止检查输入费用:

    result <- as.numeric(rep(c(exp_ind, exp_rem), each = 2) > cutoffs)
    

    最后,转换成二进制:

    result_bin <- sum(2^(seq_along(result) - 1) * result)
    

    现在我可以根据result_bin 中的值为可能的结果设置函数:

    if(result_bin == 1) {cost <- ded_ind + 0.1 * (exp_ind - ded_ind) + exp_rem }
    
    cost
    [1] 1550
    

    我们可以检查一下……

    • 高消费者会支付他的 1000,然后支付剩余 500 的 10% = 1050
    • 其他成员未达到家庭免赔额并支付全额400 + 100 = 500
    • 总数:1550

    我仍然需要创建 results_bin 值到相应函数的映射,但是在我看来,进行矢量化检查并转换唯一的二进制值比我的 ifelse 嵌套混乱要好得多。

    我是这样看的:我必须设置变量并编写函数无论如何;这节省了我 1) 显式编写所有条件,2) 我所说的冗余问题,即最终在 ifelse 结构中编写父拆分的相同“兄弟”分支,最后,3) 代码很远,远,更容易遵循。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-19
      • 2016-12-12
      • 2019-03-14
      • 1970-01-01
      • 2018-11-01
      • 1970-01-01
      • 2011-02-02
      • 2014-06-10
      相关资源
      最近更新 更多