Home > Back-end >  Conditional removal of rows in R
Conditional removal of rows in R

Time:12-16

Consider the following matrix:

testMat <- matrix(c(1,2,1,3,
                 3,2,3,3,
                 1,3,1,3,
                 2,3,3,3,
                 3,3,3,3,
                 3,2,3,1), byrow = T, ncol = 4)

and following condition:

cond <- c(0,0) # binary

Problem: If cond[1] is 0 and there is a 1 in either the first or third column, the corresponding rows will be removed. Similarly if cond[2] is 0 and there is a 1 in either the second or fourth column, the corresponding rows will be removed. For example the new matrix will be:

newMat <- testMat[-c(1,3,6),] # for cond <- c(0,0)
newMat <- testMat[-c(1,3),] # for cond <- c(0,1)
newMat <- testMat[-c(6),] # for cond <- c(1,0)
newMat <- testMat # for cond <- c(1,1)

I tried in following way which is both wrong and clumsy.

newMat <- testMat[-(cond[1] == 0 & testMat[,c(1,3)] == 1),]
newMat <- newMat[-(cond[2] == 0 & newMat[,c(2,4)] == 1),]

Can you help to find a base R solution?

CodePudding user response:

This is ugly, but seems to work:
(generalized for length of cond, assuming that the matrix has length(cond)*2 columns)

keepRows <- apply(testMat, 1,
                  function(rw, cond) {
                    logicrow <- vector(length=2)
                    for (b in 1:length(cond)) {
                      logicrow[b] <- ifelse(cond[b]==0, all(rw[b]!=1) & all(rw[length(cond) b]!=1), TRUE)
                    }
                    all(logicrow)
                  }, cond = cond)

newMat <- testMat[keepRows, ]

(edited according to comment)

CodePudding user response:

Assuming 1) cond can be of arbitrary length, 2) testMat has an even number of columns, and 3) the rule is to look at the i-th and (i 2)-th column of testMat

cond=c(0,0)

unlist(
  sapply(
    1:length(cond),
    function(i){
      j=rowSums(testMat[,c(i,i 2)]==1)
      if (cond[i]==0 & sum(j)>0) which(j>0) else nrow(testMat) 1
    }
  )
)
[1] 1 3 6

which returns the rows which satisfy your conditions, you can then remove these

testMat[-.Last.value,]
  • Related