user2409011
user2409011

Reputation:

What is wrong in this 'for loop' in R? Please see

z=c("abcD9","recde6","7gfbe","dvS1","MNM09")
d=c("abcD9","recde6","abcD9","bgfh123","dvS1")
y <- numeric(length=25)
k<-1
for ( i in 1:5) {
  for (j in  1:5) {
    a <- (z[i]==d[j])
    if( a==TRUE) y[k] <- j else y[k] <- 0
  }
  k<-k+1
}

I should get the result as 'y' as a vector (1 0 3 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0)

Upvotes: 1

Views: 88

Answers (3)

Sven Hohenstein
Sven Hohenstein

Reputation: 81683

It will work if you move k<-k+1 into the inner loop:

for ( i in 1:5)
{
  for (j in  1:5)
  {
    a <- (z[i]==d[j])
    if( a==TRUE)
      y[k] <- j
    else
      y[k] <- 0
    k<-k+1  
  }  
}

The result (y):

[1] 1 0 3 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0

By the way: You can obtain the same result with the following commands:

tmp <- sapply(z, function(vec1) !is.na(match(d, vec1)))
y <- numeric(length = length(tmp))
y[unlist(tmp)] <- which(tmp, arr.ind = TRUE)[ , 1]

Upvotes: 2

Paul Hiemstra
Paul Hiemstra

Reputation: 60924

I'd go for a more vectorized/apply loop approach:

y = do.call('c', lapply(z, function(x) ifelse(x == d, seq_along(d), 0)))
[1] 1 0 3 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0

or using expand.grid:

df = data.frame(expand.grid(d = d, z = z, stringsAsFactors = FALSE), 
                y = rep(seq_along(d), length(z)))
with(df, ifelse(z == d, y, 0))

Upvotes: 3

Simon O&#39;Hanlon
Simon O&#39;Hanlon

Reputation: 59970

You could eliminate the loop and do something vectorised like so:

pos <- t( outer( z , d , FUN = "==" ) )
pos[ pos == TRUE ] <- which( pos , arr.ind = TRUE )[,1]
as.vector(pos)
#[1] 1 0 3 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0

Upvotes: 3

Related Questions