SNT
SNT

Reputation: 1433

How to be more effective with this ifelse in R

I am going through a code base which was written some time ago. This seems to be effective and working. But for each analysis the code is thousands of lines. One part is here. I want to know if there's an effective way to cut down the code using dplyr and make it more efficient.

Sample data input:

table1 <-
  structure(
    list(
      Objective = c("apples", "bananas", "apples",
                    "oranges", "watermelon"),
      alpha = c(2.12,
              2.12, 3.8, 3.68, 6.98),
      beta = c(0.35, 0.45, 0.22, 0.38, 0.38),
      charlie = c(0.02, 0.01, 0.01, 0.02, 0.02),
      delta = c(0.01, 0.01,
              0.01, 0.02, 0.01),

      benchmark = c(0.57,
                        0.57, 0.57, 0.57, 0.57)
    ),
    row.names = c(NA, 5L),
    class = "data.frame"
  )
for (i in 1:nrow(table1)) {

  table1$cond_format[i] <-

    if(table1$Objective[i]=="" | is.na(table1$alpha[i]) | table1$benchmark[i]=="") 0 else
      if(table1$Objective[i]=="apples" & table1$alpha[i] < table1$benchmark[i] * 0.5) 1 else
        if(table1$Objective[i]=="apples" & table1$alpha[i] <= table1$benchmark[i] * 1) 2 else
          if(table1$Objective[i]=="apples" & table1$alpha[i] > table1$benchmark[i] * 2) 4 else
            if(table1$Objective[i]=="apples" & table1$alpha[i] > table1$benchmark[i] * 1) 3 else
              if(table1$Objective[i]=="bananas" & table1$beta[i] < table1$benchmark[i] * 0.5) 11 else
                if(table1$Objective[i]=="bananas" & table1$beta[i] <= table1$benchmark[i] * 1) 12 else
                  if(table1$Objective[i]=="bananas" & table1$beta[i] > table1$benchmark[i] * 2) 14 else
                    if(table1$Objective[i]=="bananas" & table1$beta[i] > table1$benchmark[i] * 1) 13 else
                      if(table1$Objective[i]=="oranges" & table1$charlie[i] < table1$benchmark[i] * 0.5) 21 else
                        if(table1$Objective[i]=="oranges" & table1$charlie[i] <= table1$benchmark[i] * 1) 22 else
                          if(table1$Objective[i]=="oranges" & table1$charlie[i] > table1$benchmark[i] * 2) 24 else
                            if(table1$Objective[i]=="oranges" & table1$charlie[i] > table1$benchmark[i] * 1) 23 else
                              if(table1$Objective[i]=="watermelon" & table1$delta[i] < table1$benchmark[i] * 0.5) 31 else
                                if(table1$Objective[i]=="watermelon" & table1$delta[i] <= table1$benchmark[i] * 1) 32 else
                                  if(table1$Objective[i]=="watermelon" & table1$delta[i] > table1$benchmark[i] * 2) 34 else
                                    if(table1$Objective[i]=="watermelon" & table1$delta[i] > table1$benchmark[i] * 1) 33 else

                                      0 }

Upvotes: 0

Views: 68

Answers (1)

Shree
Shree

Reputation: 11150

There are only 4 combinations with output being offset by certain constant for each Objective. Knowing this , the code can simplified by creating a separate table of valid Objective-Variable combos with Offset for each combo -

library(dplyr)
library(tidyr)

valid_combo <- tibble(
  Objective = c("apples", "bananas", "oranges", "watermelon"),
  Variable = c("alpha", "beta", "charlie", "delta"),
  Offset = c(0,10,20,30)
)

table1 %>% 
  gather(Variable, value, -Objective, -benchmark) %>% 
  inner_join(valid_combo, by = c("Objective", "Variable")) %>% 
  mutate(
    cond_format = case_when(
      Objective == "" | is.na(value) | benchmark == "" ~ 0,
      value < benchmark * 0.5 ~ 1,
      value <= benchmark * 1 ~ 2,
      value > benchmark * 2 ~ 4,
      value > benchmark * 1 ~ 3,
      TRUE ~ 0
    ) + Offset
  )

   Objective benchmark Variable value Offset cond_format
1     apples      0.57    alpha  2.12      0           4
2     apples      0.57    alpha  3.80      0           4
3    bananas      0.57     beta  0.45     10          12
4    oranges      0.57  charlie  0.02     20          21
5 watermelon      0.57    delta  0.01     30          31

# above output matches with your `if else` output

Upvotes: 3

Related Questions