Alternatives to Nested Ifelse Statements in R

Alternatives to nested ifelse statements in R

You can vectorize using max.col

indx <- names(df)[max.col(df[-1], ties.method = "first") + 1L]
df$firstyear <- as.numeric(sub("in", "20", indx))
df
# id in05 in06 in07 in08 in09 firstyear
# 1 a 1 0 1 0 0 2005
# 2 b 0 0 1 1 0 2007
# 3 c 0 0 0 1 0 2008
# 4 d 1 1 1 1 1 2005

Alternative to nested ifelse() statements in R

The usual way of doing this in R is probably cut; here's an example.

## some sample current values
I <- c(1e-6, 2e-6, 1e-5, 2e-5, 1e-4, 2e-4, 1e-3, 2e-3)
## define the endpoints for the different ranges
breaks <- c(-Inf, 2*10^(-6:3))
## for each range, define the percent of the original
## and the amount to add
percent <- c(0.10, 0.11, 0.12, 0.13)
dig <- c(3e-9, 3e-8, 3e-7, 3e-6)
## get the range that each value falls in
range <- cut(I, breaks, labels=FALSE)
## and multiply by the right percent and add the right extra amount
I*percent[range]/100 + dig[range]

Alternative to nested ifelse-statement // Assign seasons to month

Does this work:

> library(dplyr)
> df %>% mutate(SEASON = case_when(MONTH %in% 3:5 ~ 'Spring', MONTH %in% 6:8 ~ 'Summer', MONTH %in% 9:11 ~ 'Autumn', TRUE ~ 'Winter'))
# A tibble: 10 x 4
X1 MONTH SALES SEASON
<dbl> <dbl> <dbl> <chr>
1 1 9 209 Autumn
2 2 3 273 Spring
3 3 9 249 Autumn
4 4 7 99 Summer
5 5 9 442 Autumn
6 6 6 202 Summer
7 7 7 347 Summer
8 8 3 428 Spring
9 9 1 67 Winter
10 10 2 223 Winter
>

Alternatives to multiple ifelse in R

switch isn't really meant for something like this, cut is better:

cut(Y,c(-Inf,5,10,Inf),labels=LETTERS[1:3],right=FALSE)
[1] C C C C C B C C C C A B C A C C C C B C C C C C C C C C C C C A B C C C C
[38] C C B C C C C C C A A A C C C C C C C C A C C C C C C C C C B C C C C C C
[75] A C C C C B C C A A B C C C C A C C A C C C C C A C
Levels: A B C

Alternative for giant nested ifelse statement

You only really need to nest ifelse statements if the conditions themselves are nested. In this case, the conditions are mutually exclusive, so you can assign to each set individually. We can also be a little clever about creating your results with paste and some math rather than listing all the possibilities:

df$Period[df$Frequency == "Month"] = as.character(df$Period_No[df$Frequency == "Month"])
df$Period[df$Frequency == "Quarter"] = paste0("Q", (df$Period_No[df$Frequency == "Quarter"] - 1) %/% 3 + 1)
df$Period[df$Frequency == "YTD"] = paste0("YTD-", month.abb[df$Period_No[df$Frequency == "YTD"]])

df
# Period_No Frequency Period
# 1 1 Month 1
# 2 2 Month 2
# 3 3 Month 3
# 4 3 Quarter Q1
# 5 6 Quarter Q2
# 6 9 Quarter Q3
# 7 1 YTD YTD-Jan
# 8 2 YTD YTD-Feb
# 9 3 YTD YTD-Mar

If you like dplyr, I'd recommend the case_when function:

df %>% mutate(Period = case_when(
Frequency == "Month" ~ as.character(Frequency),
Frequency == "Quarter" ~ paste0("Q", (Period_No - 1) %/% 3 + 1),
Frequency == "YTD" ~ paste0("YTD-", month.abb[Period_No])
))

Using this sample data:

df = read.table(text = "Period_No  Frequency
1 Month
2 Month
3 Month
3 Quarter
6 Quarter
9 Quarter
1 YTD
2 YTD
3 YTD", header = T)

ifelse in R: alternatives to nesting

I would have written it like this:

rf$rs.X<- with( rf, ifelse(chl==0 & dm=="y" & gdr=="m" &
smk=="n" & age>=70 & sbp>=160, ">=40%", NA)

Then the next one (say for the low sbp cases, could have the rs.X value as the alternative:

rf$rs.X<- with( rf, ifelse(chl==0 & dm=="y" & gdr=="m" &
smk=="n" & age>=70 & sbp < 160, "30-39%", rs.X)

So that way the value is not overwritten for the non-qualifying rows.

Alternate for nested ifelse with character columns in R

Create a key/val dataset and use regex_left_join

keyval <- data.frame(comments = c("jen", "rick"),
name = c("Jennifer A", "richard"))
library(fuzzyjoin)
regex_left_join(comdata, keyval, by = "comments")


Related Topics



Leave a reply



Submit