1

So I have a table m, consisting of a random number of rows and columns. (can be any size)...

I want to do this calculation against each rows/columns totals:

  r[i] * c[j] / n;

Where r <- rowSums(m);, c <- colSums(m); and n <- sum(m);

I can do it with a double for-loop but I'm hoping to implement it now using while loops.

I wasn't going to use while loops but seems the table size can differ, I figured it was wise too.

I'm storing each value as it's found in a test vector.

This is my attempt, but I'm messing up the indices:

while(i < nrow(m)){
    while(j < ncol(m)){
        test[i] <- r[i]*c[j] / n;
        j=j+1;
        i=i+1;
    }
    j=j+1;
    i=i+1;
}

Any guidance to help me sort out my loops would be much appreciated. Thanks in advance.

update

See below for an example and expected result:

    m <- t(matrix(c(28,48,10,114), nrow=2, ncol=2));
    r <- rowSums(m); #76 124 (sum of rows)
    c <- colSums(m); #38 162 (sum of cols)
    n <- sum(m);     #200 (sum of all cells)

    test <- c(0, times length(m)); #empty vector/data frame

    #inside while loops, calc for each r and c indice:
    test[1] <- 76 *38 /200 #first calc to test[i] where i=1
    test[2] <- 124*38 /200
    test[3] <- 76*162 /200
    test[4] <- 124*162/200 #last calc to test[i] where i==length(m)
3
  • Perhaps, outer could be useful here. Something like outer(r, c, function(x, y) x * y / n) Commented Feb 23, 2014 at 22:42
  • can you add an actual example with the expected input/outputs? Since R is vectorized, simply running r * c / n will match out row sum with the corresponding column sum and then divide by the total sum...it's unclear what you want to happen when you have say three rows and ten columns...how should the data be recycled? Commented Feb 23, 2014 at 22:42
  • I've added an example. I hope this makes it clearer what I'm trying to achieve. Thanks for posting. ps. all row totals (whether 3 or 500) need to be calculated with ever column total (whether 3 or 500). Commented Feb 23, 2014 at 22:53

3 Answers 3

3

I would avoid using a for or while loop and do something like this instead:

> as.vector(outer(r,c, function(x,y) x*y/n))
[1]  14.44  23.56  61.56 100.44
Sign up to request clarification or add additional context in comments.

1 Comment

Ah excellent. This is the first I've seen of the outer function. very handy. Thanks for posting.
2

No need to use a while loop. It is always best to use vector operations in R (and any other array-based language). It makes for clearer and faster code.

nrows<-sample(1:100,1) # a random number of rows
ncols<-sample(1:100,1) # a random number of columns

#create a matrix of random numbers with our random dimnesions
m<-matrix(runif(nrows*ncols), nrow=nrows) 
n<-sum(m)
#read into outer, it creates a cartesian product of your vectors
#so you will have every r[i] multipled with every r[j]...ie what your loop is doing
r<-outer(rowSums(m),colSums(m),function(x,y) x*y/n)

Hope this helps, let me know if you have any questions.

1 Comment

Another great answer. Nice implementation. Thanks for the explanation too.
1

A more R-like solution would be to use expand.grid instead of a nested while loop:

Set-up:

> m <- matrix(1:12, 3, 4)
> m
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12
> n <- sum(m)
> r <- rowSums(m)
> c <- colSums(m)

Now:

> test <- expand.grid(r,c)
> test
   Var1 Var2
1    22    6
2    26    6
3    30    6
4    22   15
5    26   15
6    30   15
7    22   24
8    26   24
9    30   24
10   22   33
11   26   33
12   30   33
> test <- test[,1] * test[,2] / n
> test
 [1]  1.692308  2.000000  2.307692  4.230769  5.000000  5.769231  6.769231
 [8]  8.000000  9.230769  9.307692 11.000000 12.692308

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.