user8102905
user8102905

Reputation: 191

Filter matrix rows where row numbers have max difference between them

Having a matrix A like:

 1   21    3   49   59
21   33   59   67   65
 3    5    7    8   11
21   76    5    4    9

I want to get only the rows where there are no 3 or more numbers per row all having between them max difference < 10

this function should return only Row 1.

Upvotes: 2

Views: 95

Answers (3)

Eugene Brown
Eugene Brown

Reputation: 4362

Analysis of the two submitted answers:

Input:

pacman::p_load(microbenchmark)

vec <- c(1, 21, 3, 49, 59, 21, 33, 59,
     67, 65, 3, 5, 7, 8, 11, 21, 76, 5, 4, 9)

A <- matrix(vec, nrow = 4, byrow = TRUE)

returnRows <- function(x) {
  count <- 0
  for (i in 1:nrow(x)) {
    if (length(which(diff(combn(x[i,],2)) < 10)) < 3) {
      count <- c(count,i)
    }
  }
  return(x[count[-1],])
}

# dvarelas' answer
microbenchmark(returnRows(A))

# Sotos' answer
microbenchmark(A[rowSums(t(apply(A, 1, function(i)combn(i, 2, diff))) < 10) < 3,])

Output:

> microbenchmark(returnRows(A))
Unit: microseconds
          expr     min      lq     mean   median       uq    max neval
 returnRows(A) 137.113 141.124 152.6586 143.8595 154.7995 301.94   100

> microbenchmark(A[rowSums(t(apply(A, 1, function(i)combn(i, 2, diff))) < 10) < 3,])
Unit: microseconds
                                                                      expr     min      lq     mean   median     uq      max neval
 A[rowSums(t(apply(A, 1, function(i) combn(i, 2, diff))) < 10) <      3, ] 374.507 431.759 645.9935 544.4395 742.45 5324.047   100

Conclusion: The answer by dvarelas is a lot faster than the one by Sotos

Upvotes: 1

dvarelas
dvarelas

Reputation: 988

This bit of code will do. There's also a small example:

vec <- c(1, 21, 3, 49, 59, 21, 33, 59,
         67, 65, 3, 5, 7, 8, 11, 21, 76, 5, 4, 9)

A <- matrix(vec, nrow = 4, byrow = TRUE)

returnRows <- function(x) {
  count <- 0
  for (i in 1:nrow(x)) {
    if (length(which(diff(combn(x[i,],2)) < 10)) < 3) {
      count <- c(count,i)
    }
  }
  return(x[count[-1],])
}

## example

returnRows(A)

Upvotes: 5

Sotos
Sotos

Reputation: 51592

You cun find the diff of all combinations of values, and use rowSums to filter, i.e.

A[rowSums(t(apply(A, 1, function(i)combn(i, 2, diff))) < 10) < 3,]
#[1]  1 21  3 49 59

Upvotes: 3

Related Questions