Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exceeding limit with ifelse statements

Problem: I wrote a gigantic piece of code with over 100 ifelse statements only to learn that there is a limit on the number of ifelse statements: exceeding 50 throws an error. Anyway, I know there is a more efficient way to do what I am trying to do.

Goal: Trying to write a function to recode many variants of strings (see below example) into clear categories (e.g. below). I use str_detect to give T/F and then change into the correct category based on response. How can I do this without over 100 ifelse statements (I have a lot more categories).

Example:

mydf <- data_frame(answer = sample(1:5, 10, replace = T),
                location = c("at home", "home", "in a home", 
"school", "my school", "School", "Work", "work",
                         "working", "work usually"))

loc_function <- function(x) {
  home <- "home"
  school <- "school"
  work <- "work"
  ifelse(str_detect(x, regex(home, ignore_case = T)), "At Home",
     ifelse(str_detect(x, regex(school, ignore_case = T)), "At 
School",
            ifelse(str_detect(x, regex(work, ignore_case = T)), "At 
Work", x)))
}

### Using function to clean up messy strings (and recode first column too) into clean categories
mycleandf <- mydf %>%
  as_data_frame() %>%
  mutate(answer = ifelse(answer >= 2, 1, 0)) %>%
  mutate(location = loc_function(location)) %>%
  select(answer, location)

mycleandf

# A tibble: 10 x 2
   answer  location
    <dbl>     <chr>
 1      1   At Home
 2      1   At Home
 3      1   At Home
 4      1 At School
 5      1 At School
 6      1 At School
 7      1   At Work
 8      0   At Work
 9      1   At Work
10      0   At Work
like image 284
tall_table Avatar asked Dec 03 '25 08:12

tall_table


1 Answers

You can put your patterns in a named vector, (notice the Other = "", this is a fall back when none of your pattern matches the string):

patterns <- c("At Home" = "home", "At School" = "school", "At Work" = "work", "Other" = "")

Then loop through the pattern and check if the string contains pattern:

match <- sapply(patterns, grepl, mydf$location, ignore.case = T)

Finally build up the new column buy checking the name of the matched pattern which is the one you want to replace with, if nothing matches, fall back to Other:

mydf$clean_loc <- colnames(match)[max.col(match, ties.method = "first")]
mydf

# A tibble: 10 x 3
#   answer     location clean_loc
#    <int>        <chr>     <chr>
# 1      3      at home   At Home
# 2      3         home   At Home
# 3      3    in a home   At Home
# 4      3       school At School
# 5      2    my school At School
# 6      4       School At School
# 7      5         Work   At Work
# 8      1         work   At Work
# 9      2      working   At Work
#10      1 work usually   At Work
like image 167
Psidom Avatar answered Dec 05 '25 23:12

Psidom