Reputation: 191
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
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
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
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