缩短嵌套ifelse

时间:2017-03-27 11:25:15

标签: r if-statement data.table

如果给出以下数据表,并且我们希望将x1与x2和x5进行比较,则可以使用以下数据:

set.seed(1)
library(data.table)
TDT <- data.table(x1 = round(rnorm(100,0.75,0.3),2),
                  x2 = round(rnorm(100,0.75,0.3),2),
                  x3 = round(rnorm(100,0.75,0.3),2),
                  x4 = round(rnorm(100,0.75,0.3),2),
                  x5 = round(rnorm(100,0.75,0.3),2))

TDT[,compare := ifelse(x1 < x2,1,ifelse(x1 < x3,2,ifelse(x1 < x4,3,ifelse(x1 < x5,4,5))))]

所以,如果是x1 < x2,那么compare == 1等等

现在在我的例子中,我有更多的列来比较x1和。有没有办法更简洁地写这个,即没有嵌套的ifelse?

2 个答案:

答案 0 :(得分:5)

我们可以使用Map

中的max.coldata.table来执行此操作
TDT[, compare := {d1 <- as.data.table(Map(function(x) x1 < x, .SD))
       max.col(d1, "first") *(c(5, 1)[((Reduce(`+`, d1)!=0)+1)])}, .SDcols = x2:x5]

#OP's code
v1 <- TDT[, ifelse(x1 < x2,1,ifelse(x1 < x3,2,ifelse(x1 < x4,3,ifelse(x1 < x5,4,5))))]
identical(v1, TDT$compare)
#[1] TRUE

答案 1 :(得分:5)

这节省了一些打字并且易于阅读。

TDT[, compare := dplyr::case_when(
      x1 < x2 ~ 1,
      x1 < x3 ~ 2,
      x1 < x4 ~ 3,
      x1 < x5 ~ 4,
      TRUE ~ 5)]

如果你有这么多专栏,你不想通过名字提及它们,那么你可以使用:

apply(TDT, 1, function (x) which(x[1] < x[2:5])[1]) 

其中x [2:5]应替换为相关的列集。