momo96
momo96

Reputation: 53

Vectorize nested for loop, R

Actually, I want to create a vector "compare" form another vector "data". I want to compare each element in "data" with himself and all the element that follows in the vector. If there is a tie I append 1 to "compare" if not I append 0. For example:

data=c(3,6,7,3)
# I compare 3 to 3, 6, 7 and 3
# Then I compare 6 to 6, 7, and 3
# Then 7 to 7 an 3
# Then 3 to 3 so I get
compare=c(1,0,0,1,1,0,0,1,0,1)

Here is what I have done:

for(i in 1:length(data))
{
  for(j in 0:(length(data)-i))
  {
     if (data[i]==data[i+j])
     {
        compare=append(compare,1)
     }
     else
     {
        compare=append(compare,0)
     }
  }
}

Is there any way to vectorize this kind of comparison between vectors elements?

Upvotes: 2

Views: 223

Answers (3)

Roland
Roland

Reputation: 132706

We can use dist:

data=c(3,6,7,3)
res <- as.matrix(dist(data))
res <- res < .Machine$double.eps #find elements with distance of 0
diag(res) <- 1
res[lower.tri(res, TRUE)]
#[1] 1 0 0 1 1 0 0 1 0 1

Upvotes: 3

Ronak Shah
Ronak Shah

Reputation: 388907

We can use outer to compare data with itself and then extract lower triangular data so that we get output of only the data which follows the current value.

mat <- +(outer(data, data, `==`))
mat[lower.tri(mat, diag = TRUE)]
#[1] 1 0 0 1 1 0 0 1 0 1

Upvotes: 2

Clemsang
Clemsang

Reputation: 5481

You can use sapply on index:

as.numeric(unlist(sapply(1:length(data), function(k) data[k] == data[k:length(data)])))
[1] 1 0 0 1 1 0 0 1 0 1

Current value of index k is compared with all values equal or after k. unlist allows to concatenate the result of each iteration k. Finally as.numerictransforms booleans to integers.

Upvotes: 1

Related Questions