Achal Neupane
Achal Neupane

Reputation: 5729

How to formulate multiple if conditions in R?

I have this data called dft. I want to add Ch1.. Ch4 as chr column in dft. I have if else condition, but it doesn't seem to work. What is wrong with my if else statement below?

dft <- structure(list(pos_coverage = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 
    position = 1:10, neg_coverage = c(0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0)), .Names = c("pos_coverage", "position", "neg_coverage"
), row.names = c(NA, 10L), class = "data.frame")


Ch1 <- 1:2
Ch2 <- 3:5
Ch3 <- 6:8
Ch4 <- 9:10

if( dft$position == Ch1){
  dft$chr <- "Ch1"
} else if (dft$position == Ch2){
  dft$chr <- "Ch2"
} else if (dft$position == Ch3){
  dft$chr <- "Ch3"
} else {dft$chr <- "Ch4"}

Upvotes: 1

Views: 58

Answers (3)

jay.sf
jay.sf

Reputation: 73692

To avoid ifelse() you could consider subsets of your data.

dft$chr <- NA
dft$chr[dft$position %in% Ch1] <- "Ch1"
dft$chr[dft$position %in% Ch2] <- "Ch2"
dft$chr[dft$position %in% Ch3] <- "Ch3"
dft$chr[dft$position %in% Ch4] <- "Ch4"

With a lapply() and a test set we can automate this.

test.set <- ls(pattern="Ch")
# # or
# test.set <- paste0("Ch", 1:4)

l <- lapply(test.set, function(x) {
  sub <- dft$position %in% get(x)
  dft$chr[sub] <- x
  dft[sub, ]
  })

Result

> do.call(rbind, l)
   pos_coverage position neg_coverage chr
1             0        1            0 Ch1
2             0        2            0 Ch1
3             0        3            0 Ch2
4             0        4            0 Ch2
6             0        6            0 Ch3
7             0        7            0 Ch3
8             0        8            0 Ch3
9             0        9            0 Ch4
10            0       10            0 Ch4

Upvotes: 1

Parfait
Parfait

Reputation: 107767

Consider nested ifelse and change == to %in%:

dft$chr <- with(dft, ifelse(position %in% Ch1, "Ch1", 
                           ifelse(position %in% Ch2, "Ch2",
                                  ifelse(position %in% Ch3, "Ch3", "Ch4")
                                 )
                           )
               )

Rextester demo

Upvotes: 5

akrun
akrun

Reputation: 887881

A better option would be to create a key/val data with stack and then do a join

library(tidyverse)
stack(mget(paste0("Ch", 1:4))) %>% 
   right_join(dft, by = c("values" = "position")) %>%
   rename(chr = ind)
#   values chr pos_coverage neg_coverage
#1       1 Ch1            0            0
#2       2 Ch1            0            0
#3       3 Ch2            0            0
#4       4 Ch2            0            0
#5       5 Ch2            0            0
#6       6 Ch3            0            0
#7       7 Ch3            0            0
#8       8 Ch3            0            0
#9       9 Ch4            0            0
#10     10 Ch4            0            0

Upvotes: 3

Related Questions