DR41
DR41

Reputation: 23

Nested for loops in r

I have 2 data frames.

M looks like this:

      vec_a vec_b vec_c
    A   0.0     0     0
    B   0.5     0     0
    C   0.5     1     1  

Rank looks like this:

    rk_ini
    0.3333333
    0.3333333
    0.3333333

I would like to multiply each values in row 1 of M by the value in row 1 of Rank and add these products together. Then do the same for row 2 and then row 3.

Afterwards I would like to concatenate these 3 values into a vector and column bind them on to the second data frame Rank. This should be repeated with the new values I just calculated to produce 3 more values to bind on to Rank and repeated whatever number of times I specify in the beginning of my function. Continually binding on a new column on to `Rank.

## iterate t times to get rank
for(i in 1:t) {
  for (j in 1:(nrow(M))) {
    nr1[j] <- sum((Rank[j, i] * M[j, 1]), 
                  (Rank[j, i] * M[j, 2]), 
                  (Rank[j, i] * M[j, 3]))

    nextrank <- c(nextrank, nr1[j])
  }
  Rank <- cbind(Rank, nextrank[i])
}

Finally here are the results:

      rk_ini     nextrank[i] nextrank[i] nextrank[i] nextrank[i] nextrank[i]
    A 0.3333333        0     0.1666667   0.8333333           0           0
    B 0.3333333        0     0.1666667   0.8333333           0           0
    C 0.3333333        0     0.1666667   0.8333333           0           0

The results should look more like this:

      rk_ini     nextrank[i] nextrank[i] nextrank[i] nextrank[i] nextrank[i]
    A 0.3333333       0          ....
    B 0.3333333   0.1666667      ....
    C 0.3333333   0.8333333      ....

With each successive row in the new column being the sum of the products of the previous column multiplied by each value in the corresponding row in M.

I've tried numerous things and this last does not produce any errors, however it also does not produce the results I am looking for. Any help you can provide in understanding what is going on here will be greatly appreciated.

Thanks!

Upvotes: 2

Views: 145

Answers (4)

jbaums
jbaums

Reputation: 27388

If I understand correctly, then referring to the data in your post, you want the first element of your new Rank vector to be the sum of the products the first element of Rank and the elements of row A (i.e., sum(M[1, ] * R[1])), the second element to be the sum of the products of second element of Rank and the elements of row B (sum(M[2, ] * R[2])), and so on. You then want to repeat this calculation with the new Rank vector taking the place of the original Rank vector.

If this is the case, then I believe the output of the solution provided by @rnso is accurate.

Here's a vectorised approach that achieves the same, taking advantage of the fact that the nth operation for row i is equivalent to Rank[i] * rowSums(M)[i]^n.

M <- matrix(c(0, 0, 0,
              0.5, 0, 0,
              0.5, 1, 1), ncol=3, byrow=TRUE)

R.init <- c(0.3333333, 0.3333333, 0.3333333)

n <- 5
t(mapply(function(m, r)  r * m^(seq_len(n)), rowSums(M), R.init))

#           [,1]       [,2]       [,3]        [,4]        [,5]
# [1,] 0.0000000 0.00000000 0.00000000  0.00000000  0.00000000
# [2,] 0.1666666 0.08333332 0.04166666  0.02083333  0.01041667
# [3,] 0.8333333 2.08333312 5.20833281 13.02083203 32.55208008

Upvotes: 0

agstudy
agstudy

Reputation: 121568

Here a vectorized way using matrix multiplication %*% and replicate:

M <- as.matrix(M)
R <- as.matrix(R)
mm <- replicate(5,R <<- M%*%R,simplify = TRUE)

        [,1]      [,2]      [,3]      [,4]      [,5]
[1,] 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000
[2,] 0.1666666 0.0000000 0.0000000 0.0000000 0.0000000
[3,] 0.8333332 0.9999999 0.9999999 0.9999999 0.9999999

Where M and R are;

M <- read.table(text='
vec_a vec_b vec_c
A 0.0   0    0
B 0.5   0    0
C 0.5   1    1',header=TRUE)
R <- read.table(text='
rk_ini
0.3333333
0.3333333
0.3333333',header=TRUE)

Upvotes: 3

rnso
rnso

Reputation: 24535

Try:

> M
  vec_a vec_b vec_c
A   0.0     0     0
B   0.5     0     0
C   0.5     1     1
> 
> rank
       rank
1 0.3333333
2 0.3333333
3 0.3333333
> 
> for(i in 1:4){
+ M$rank = rank[,length(rank)]
+ M$new = apply(M, 1, function(x) x[4]*sum(x[1],x[2],x[3]) )
+ rank[,length(rank)+1] = M$new 
+ }

> M = M[c(1:3)]
> M
  vec_a vec_b vec_c
A   0.0     0     0
B   0.5     0     0
C   0.5     1     1

> print(rank)
       rank        V2         V3         V4          V5
1 0.3333333 0.0000000 0.00000000 0.00000000  0.00000000
2 0.3333333 0.1666666 0.08333332 0.04166666  0.02083333
3 0.3333333 0.8333333 2.08333313 5.20833281 13.02083203
> 

Upvotes: 0

Ujjwal
Ujjwal

Reputation: 3158

Modify your code as shown:

for(i in 1:t) {
            for (j in 1:(nrow(M))) {
            nr1[j] <- sum((Rank[j, i] * M[j, 1]), (Rank[j, i] * M[j, 2]), (Rank[j, i] * M[j, 3]))

            nextrank <- c(nextrank, nr1[j])
            }

            Rank <- cbind(Rank, nextrank[i*(1:3)])    **key step**
    }                

    Rank      
    }

Upvotes: 1

Related Questions