I'm facing nested ifelse()
structures:
df1$var <- ifelse(x < a, u, ifelse(x < b, v, ifelse(x < c, w, ...)))
whereby the u, v, w, ...
s are actually functions.
A dumbed down working example would be
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"))))
I presume there could be ideally a base R method (for sake of speed) to simplify such code; eventually a function as
rave.ifelse(x, 1=s, 2=t, ...)
I took a glance at cut(x, 5)
but it confused me from this point of view.
Note: Values of x
could be either numbers or factors, ==
could also be any logical operator and the s, t, ...
are actually functions.
edit:
Note: The number of ifelse()
s is known and large. The solution really should fit to the df1$var <- ifelse(x < a, u, ifelse(x < b, v, ifelse(x < c, w, ...)))
situation, when the u, v, w, ...
s are functions, e.g. u=sample(0:9, 1), v=runif(1),...
. It should not be significantly slower than ifelse()
.
You could use case_when
from the dplyr
library:
df1$y <- case_when(
x == 1 ~ "s",
x == 2 ~ "t",
x == 3 ~ "u",
x == 4 ~ "v",
TRUE ~ "w"
)
Note that the final case above (TRUE
) is the blanket else condition which will catch all cases not matching any earlier conditions.
Since you insist on base R, here are two possibilities:
Define a mapping data.frame
:
# Define mapping
map <- cbind.data.frame(
x = c(1, 2, 3, 4, NA),
y = c("s", "t", "u", "v", "w"));
Method 1: match
entries from map
to df1
.
# match entries
df1$y <- map[match(df1$x, map$x), 2];
df1$y[is.na(df1$y2)] <- "w";
Method 2: Loop through all mappings, and replace using direct indexing:
# 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];
Output:
tail(df1);
# x y
#95 4 v
#96 1 s
#97 4 v
#98 2 t
#99 4 v
#100 1 s
Note, the second method will also work for inequalities.
set.seed(2017);
df1 <- data.frame(x = rbinom(100, 5, .5))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With