0

I have a script that creates a column so that I know which rule should be applied to each row in a dataframe.

EndoSubset$FU_Group<-ifelse(EndoSubset$IMorNoIM=="No_IM","Rule1",
                            ifelse(EndoSubset$IMorNoIM=="IM","Rule2",
                             ifelse(EndoSubset$IMorNoIM=="AnotherIM","Rule3",
                           "NoRules")))

I want to make this into a function so that there can be any number of rules and any number of conditions for a column so it could be:

  EndoSubset$FU_Group<-ifelse(EndoSubset$IMorNoIM=="No_IM","Rule1",
                                ifelse(EndoSubset$IMorNoIM=="IM","Rule2",
                                ifelse(EndoSubset$IMorNoIM=="AnotherIM","Rule3",
                                ifelse(EndoSubset$IMorNoIM=="SomeOtherIM","Rule4",
                                ifelse(EndoSubset$IMorNoIM=="LotsOfIM","Rule5",
                               "NoRules")))

I understand that I can use the ellipsis for this but I don't understand how to use this for both the conditional string ("No_IM, "IM,"AnotherIM", etc) and the Rule string at the same time ("Rule1","Rule2","Rule3" etc.)

Sebastian Zeki
  • 6,690
  • 11
  • 60
  • 125
  • Create a lookup data.frame and use merge. – Roland Dec 25 '16 at 10:31
  • @Roland. Not sure that answers the question. I want to create it as a function for reuse and therefore want to have a variable number of parameters for the function. How do I do this? – Sebastian Zeki Dec 25 '16 at 10:34
  • maybe use `factor`. i.e. `get_group <- function(x){factor(x$IMorNoIM, levels = unique(x$IMorNoIM), labels = c(paste0('rule', seq(length(unique(x$IMorNoIM))))))}` – Sotos Dec 25 '16 at 10:51
  • As I understand your description, you might make something out of the following: `ff = function(x, matches, replacements, other) { ans = replacements[match(x, matches)]; ans[is.na(ans)] = other; ans }`. And, e.g., with `set.seed(166); x = sample(letters[1:5], 20, TRUE)`, see `ff(x, c("a", "d"), c("rule1", "rule4"), "NoRules")` or `ff(x, c("a", "d", "c"), c("rule1", "rule4", "rule3"), "NoRules")` – alexis_laz Dec 25 '16 at 11:18

1 Answers1

2

This answer is based upon another, incomplete answer that has been deleted.

You can use case_when() from the dplyr package to achieve this. It takes an arbitrary number of conditions. Since you don't give a reproducible example, I show how this works with mtcars:

library(dplyr)
mtcars$cyl_group <- case_when(mtcars$cyl == 4 ~ "Rule1",
                              mtcars$cyl == 6 ~ "Rule2",
                              TRUE ~ "NoRules")
mtcars[2:5, ]
##                    mpg cyl disp  hp drat    wt  qsec vs am gear carb cyl_group
## Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4     Rule2
## Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1     Rule1
## Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1     Rule2
## Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2   NoRules

As you can see, you can easily connect a condition with a value using ~. Your two examples can probably be solved like this (I cannot check this, since you don't give your data):

EndoSubset$FU_Group <- case_when(EndoSubset$IMorNoIM == "No_IM" ~ "Rule1",
                                 EndoSubset$IMorNoIM == "IM" ~ "Rule2",
                                 EndoSubset$IMorNoIM == "AnotherIM" ~ "Rule3",
                                 TRUE ~ "NoRules")

EndoSubset$FU_Group <- case_when(EndoSubset$IMorNoIM == "No_IM" ~ "Rule1",
                                 EndoSubset$IMorNoIM == "IM" ~ "Rule2",
                                 EndoSubset$IMorNoIM == "AnotherIM" ~ "Rule3",
                                 EndoSubset$IMorNoIM == "SomeOtherIM" ~ "Rule4",
                                 EndoSubset$IMorNoIM == "LotsOfIM" ~ "Rule5",
                                 TRUE ~ "NoRules")
Stibu
  • 15,166
  • 6
  • 57
  • 71