如何简化基R中嵌套ifelse()结构的处理?

时间:2018-02-14 02:25:52

标签: r if-statement

我面对嵌套的ifelse()结构:

df1$var <- ifelse(x < a, u, ifelse(x < b, v, ifelse(x < c, w, ...)))

其中u, v, w, ...实际上是函数

一个愚蠢的工作例子是

df1 <- data.frame(x = rbinom(100, 5, .5))
df1$y <- ifelse(x == 1, "s", ifelse(x == 2, "t", 
                                    ifelse(x == 3, "u", ifelse(x == 4, "v", "w"))))

我认为理想情况下可以使用 基础R 方法(为了速度)来简化此类代码;最终是一个函数

rave.ifelse(x, 1=s, 2=t, ...)

我瞥了一眼cut(x, 5)但是从这个角度来看我很困惑。

注意: x的值可以是数字或因子,==也可以是任何逻辑运算符,而s, t, ...实际上是函数

编辑:

注意: ifelse()的数量已知并且很大。当df1$var <- ifelse(x < a, u, ifelse(x < b, v, ifelse(x < c, w, ...)))是函数时,解决方案确实应该适合u, v, w, ...情况。 u=sample(0:9, 1), v=runif(1),...。它不应该明显慢于ifelse()

4 个答案:

答案 0 :(得分:3)

您可以使用TRUE库中的case_when

 catch (Exception ex)
        {
            return InternalServerError(new ApplicationException("Something went wrong in this request. internal exception: " + ex.Message));
        }

请注意,上面的最后一个案例(<?php echo str_replace("world","Peter","Hello world!"); ?>)是覆盖其他条件,它将捕获所有不符合任何早期条件的案例。

答案 1 :(得分:2)

既然你坚持使用基础R,这里有两种可能性:

定义映射data.frame

# Define mapping
map <- cbind.data.frame(
    x = c(1, 2, 3, 4, NA),
    y = c("s", "t", "u", "v", "w"));

方法1:从matchmap的{​​{1}}条目。

df1

方法2:遍历所有映射,并使用直接索引替换:

# match entries
df1$y <- map[match(df1$x, map$x), 2];
df1$y[is.na(df1$y2)] <- "w";

输出:

# for loop
df1$y <- factor("w", levels = map$y);
for (i in 1:nrow(map)) df1$y[df1$x == map$x[i]] <- map$y[i];

注意,第二种方法也适用于不等式。

样本数据

tail(df1);
#    x y
#95  4 v
#96  1 s
#97  4 v
#98  2 t
#99  4 v
#100 1 s

答案 2 :(得分:2)

base R中,如果要替换多个元素,请创建一个键/值数据集并执行merge

keyval <- data.frame(x = c(1, 2, 3, 4), y = c("s", "t", "u", "v"), stringsAsFactors = FALSE)
new <- merge(df1, keyval, by = 'x', all.x = TRUE)[['y']]
new[is.na(new)] <- "w"
df1$x <- new

数据

set.seed(24)
df1 <- data.frame(x = rbinom(100, 5, .5))

答案 3 :(得分:0)

我会创建一个空向量,然后逐个填充每个条件。

df1$y = rep(NA,nrow(df1))
df1$y[x < a] = u(x[x < a])
df1$y[x > a & x < b] = v(x[x > a & x < b])
df1$y[x > b & x < c] = w(x[x > b & x < c])
...

我发现这是设置值的最清晰的方法,我发现当你有比嵌套的ifelse语句更多的条件时,一眼就能看到发生的事情。

df1$y = ifelse(x < a, u(x), ifelse(x < b, v(x), ifelse(x < c, w(x), ...)) )

对此的改进是预定义条件元素,即每组只计算一次:

aEls = which(x < a)
bEls = which(x > a & x < b)
cEls = which(x > b & x < c)
...

y = rep(NA,nrow(df1))
y[aEls] = u(x[aEls])
y[bEls] = v(x[bEls])
y[cEls] = w(x[cEls])
...

df$y = y