【问题标题】:Complex rules for a derived variable in RR中派生变量的复杂规则
【发布时间】:2016-08-31 22:27:44
【问题描述】:

我正在尝试根据 4-6 个其他分类变量的值组合创建一个分类变量。这些组合背后没有数学逻辑,它是非常“I在E之前,除了C之后”类型的东西。

在 SAS 中,我会这样做(调用原始变量 A-F,以及新变量 newvar):

if A=1 and F=2 then newvar = 1;
else if A=2 and B=5 then newvar = 2;
else if B=3 and D=2 then newvar = 3;
else if A=7 and C=2 and F = 1 then newvar = 4;
(several more lines like that)
else newvar=0;

上面示例中的重要一点是能够按顺序向下级联条件列表,直到满足一个条件,然后停止而不评估任何进一步的条件。例如,“B=3 和 D=2”只有在没有满足放在它们前面的其他条件时才有意义。

但是在 R 中,似乎没有办法在进行变量赋值时将一大堆 else if 放在一起,因为它是使用子集运算符完成的。因此,相反,我发现自己必须以相反的顺序编写规则,以便更高优先级的规则按顺序应用,并覆盖前面的规则所做的:

data$newvar <- 0
(a bunch of other lines with conditions)
data$newvar[A == 7 & C == 2 & F == 1] <- 4
data$newvar[B == 3 & D == 2] <- 3
data$newvar[A == 2 & B == 5] <- 2
data$newvar[A == 1 & F == 2] <- 1

这可行,但它似乎效率低下且混乱,因为与在 SAS 中重复使用“else if”和“else”不同,这里每个条件都被评估,并且 newvar 可能在达到其最终值之前被覆盖多次。

我对 R 还很陌生,还没有完全理解“应用”函数系列——有没有什么方法可以编写一个函数来实现我的规则,使用 R 的 if/else if/else,然后将其应用于数据框中的所有行?或者其他比上面的示例代码更好的方法?

(我尝试过的其他东西:“ifelse”包和“car”包中的“recode”函数。这些似乎都不能同时使用多个变量和多个条件。)

【问题讨论】:

  • 但与 SAS 不同,R 不会逐行逐行检查每个案例,并根据一定数量的 if-then-else 条件分层检查每个案例,并为每行分配一次。相反,它将子集到与单个 if 语句匹配的数据块,这可能与其他 if 语句重叠,仅分配“if 语句数”次。效率/混乱程度在某种程度上是主观的,具体取决于您看待它的方式。
  • 另外,with(dat, ifelse(A==7 &amp; C==2 &amp; F==1, 4, ifelse(B==3 &amp; D==2, 3, ifelse(A==2 &amp; B==5, 2, ifelse(A==1 &amp; F==2, 1, 0))))) 也差不多,因为有人在下面发帖,但由于某种原因被删除了。
  • 这可以说是重复的:stackoverflow.com/questions/35348701/…

标签: r


【解决方案1】:

考虑一下如何在 Excel 中使用嵌套的 if 语句来实现。

data$newvar <- NA #i like to populate with null first so I can check logic later
data$newvar <- ifelse(data$A == 2 & data$F == 2 , 1, 
ifelse(data$A == 2 & data$B == 5, 2, 
ifelse(data$B == 3 & data$D == 2, 3, 
ifelse(data$A == 7 & data$C == 2 & data$F == 1, 4, 0))))

【讨论】:

  • 谢谢!这看起来是一种很好且非常灵活的方法!
【解决方案2】:

您可以使用布尔数学:

data$newvar <- with(data, 
          (A == 7 & C == 2 & F == 1)* 4 +
          (B == 3 & D == 2)* 3 +
          (A == 2 & B == 5)* 2 +
          (A == 1 & F == 2)* 1
                    )

这不提供除 0 以外的任何其他默认值,但由于这是您选择的默认值,所以一切都很好。此变体应在不“添加”的情况下提供最高匹配。

data$newvar <- with(data, pmax( 
      (A == 7 & C == 2 & F == 1)* 4,
      (B == 3 & D == 2)* 3,
      (A == 2 & B == 5)* 2,
      (A == 1 & F == 2)* 1,
       0  )      )

【讨论】:

  • 再想一想,我认为这在这里行不通,因为您可能会遇到多个条件匹配的情况(例如,“B==3 和 D==2”以及“A ==1 和 F==2") 而不是分层应用规则以便只有一个匹配,您将获得所有匹配规则的系数的总和。不过,这是一个非常简洁和聪明的想法!
  • 您是否想知道多个组合是否匹配?我还想指出,您接受的答案并不能满足您的要求,嵌套的 ifelse 策略不会有任何覆盖。第一个匹配的组合将返回其第二个参数。如果您真的希望最后一个匹配的组合“获胜”,我可以使用布尔代数来做到这一点。
猜你喜欢
  • 2012-05-13
  • 2011-12-21
  • 1970-01-01
  • 2017-08-05
  • 1970-01-01
  • 1970-01-01
  • 2021-12-03
  • 1970-01-01
  • 2021-11-19
相关资源
最近更新 更多