Home > OS >  Conditional assignment of vector in R
Conditional assignment of vector in R

Time:03-17

I'd like to assign a vecotr based on a conditional statement. How do I do this? This is what I have tried:

zero_rows <- ifelse(i == 1, c(2,3,4,7,12),
               ifelse(i == 2, c(4,7,12),
               ifelse(i == 3, c(2,3,4,7,9,12),
               ifelse(i == 4, c(4,7,9),
               ifelse(i == 5, c(4,12),
               ifelse(i == 6, c(9,12),
               ifelse(i == 7, 12,
               ifelse(i == 8, c(2,3,4,7,9,12), 0))))))))

and


  zero_rows <- case_when(i == 1 ~ c(2,3,4,7,12),
                         i == 2 ~ c(4,7,12),
                         i == 3 ~ c(2,3,4,7,9,12),
                         i == 4 ~ c(4,7,9),
                         i == 5 ~ c(4,12),
                         i == 6 ~ c(9,12),
                         i == 7 ~ 12,
                         i == 8 ~ c(2,3,4,7,9,12),
                         TRUE ~ 0)

CodePudding user response:

It may be a case for switch

fn <- function(i) {
   i <- as.character(i)
   switch(i, 
         "1" = c(2,3,4,7,12),
          "2" = c(4,7,12),
          "3" = c(2,3,4,7,9,12),
          "4" = c(4,7,9),
          "5" = c(4,12),                              
          "6" = c(9,12),
          "7" = 12,
          "8" = c(2,3,4,7,9,12), 
         0)


}

-testing

> fn(1)
[1]  2  3  4  7 12
> fn(2)
[1]  4  7 12
> fn(3)
[1]  2  3  4  7  9 12
> fn(9)
[1] 0
> fn(10)
[1] 0

If we want to do this on each value of a column ('col1'), use rowwise and wrap the output in a list

library(dplyr)
df1 %>%
    rowwise %>%
    mutate(out = list(fn(col1)))

Or with map

library(purrr)
df1 %>%
     mutate(out = map(col1, fn))

ifelse/if_else/case_when - expects all the arguments to be of same length. Based on the code showed, it is not the case where the length differ based on the input arguments

CodePudding user response:

It would be most natural to use i as an index, like so:

l <- list(c(2, 3, 4, 7, 12),
          c(4, 7, 12),
          c(2, 3, 4, 7, 9, 12),
          c(4, 7, 9),
          c(4, 12),
          c(9, 12),
          12,
          c(2, 3, 4, 7, 9, 12))

zero_rows <- ifelse(i %in% seq_along(l), l[i], list(0))

Though it would be safer and faster to avoid ifelse altogether:

ok <- i %in% seq_along(l)
zero_rows <- rep.int(list(0), length(i))
zero_rows[ok] <- l[i[ok]]

The first approach assumes that the elements of i are all greater than or equal to 1. The second approach supports any numeric i.

CodePudding user response:

We can try nested ifelse along with list like below

f <- function(i) {
    ifelse(i == 1, list(c(2, 3, 4, 7, 12)),
        ifelse(i == 2, list(c(4, 7, 12)),
            ifelse(i == 3, list(c(2, 3, 4, 7, 9, 12)),
                ifelse(i == 4, list(c(4, 7, 9)),
                    ifelse(i == 5, list(c(4, 12)),
                        ifelse(i == 6, list(c(9, 12)),
                            ifelse(i == 7, list(12),
                                ifelse(i == 8, list(c(2, 3, 4, 7, 9, 12)), 0)
                            )
                        )
                    )
                )
            )
        )
    )[[1]]
}
  • Related