3

I have a kind of obvious question about doing a double loop in R and could not find the answer on this website. I am using the following code:

mu <- c(0, .2, .5, .8)
sco <- matrix(nrow = 50, ncol = 4*10)

for (mu in mus) {
  for (i in 1:10) {
    sco[ ,i] <- mu + rnorm(n = 50, mean = 0, sd = 1)
  }
}

I am now getting 10 columns with mu + random numbers, but what I want to get is 40 columns in which the first 10 columns represent mu is 0 + random number, columns 11 to 20 represent 0.2 + random number, etc.

How do I have to modify my code in order to get these above described results?

Thank you in advance!

User33
  • 294
  • 3
  • 10

3 Answers3

4

Isn't it so that the variance is in all columns the same? Why not creating the matrix with 50*40 Standard-normal random numbers and then add 0 to the first ten columns, 0.2 to the next ten and so forth?!

EDIT:

An example would look like this:

result <- matrix(rnorm(50*40,mean=0,sd=1),ncol=40)
mu <- c(rep(0,10),rep(10,10),rep(20,10),rep(30,10))

result <- t(t(result) + mu)

I forgot how to add a vector column-wise, hence the ugly work around with 2 transpose... And I chose different values for mu in order to make the result more clear.

The loop solution would look like this (although I wouldn't use this code, but you asked for it...)

mus <- c(0, 10, 20, 30)
sco <- matrix(nrow = 50, ncol = 4*10)

for (mu in 1:4) {
  for (i in 1:10) {
    sco[ ,i+(mu-1)*10] <- mus[mu] + rnorm(n = 50, mean = 0, sd = 1)
  }
}
Daniel Fischer
  • 3,280
  • 1
  • 18
  • 29
  • Thank you, I think your suggestion is a proper solution for now. However, I also want to get some more understanding of the loop function in R. Thus, recommendations for how doing this in R are highly appreciated. – User33 Feb 10 '13 at 11:43
  • We are already giving you on how to do this in R. Using for loops is R is seldom necessary, on often much slower – Paul Hiemstra Feb 10 '13 at 11:50
  • If you really insist on using loops, you should change the index `i`. It runs from 1 to 10, so you only write into the first ten columns. The index should go from 1 to 40. But in R it is usually so that you can avoid loops. – Daniel Fischer Feb 10 '13 at 12:00
  • 1
    To add column-wise, reorder mu: `mu <- c(0,10,20,30); result <- result + rep(mu, each=10*50)` – Matthew Lundberg Feb 11 '13 at 02:05
2

I'd do something like:

return_numbers = function(mu_value) {
     matrix(mu_value + rnorm(50 * 10), 50, 10)
  }
dat = do.call("cbind", lapply(mu, return_numbers))

and skip the for loop entirely. I skip the first loop by generating all the numbers for the first ten rows all at once, and then resizing the vector into a matrix. I skip the second loop by using lapply to loop over the mu values. Finally, I use cbind to put them into one data structure.

Paul Hiemstra
  • 59,984
  • 12
  • 142
  • 149
  • Thank you for your comment. I see that this will work too, but I prefer to use the loop function. This part of my code will be expanded with some other loops, so it will not work for my purposes. – User33 Feb 10 '13 at 11:48
  • 1
    If you are going to add even more loops I would defintely use `apply` style loops and vectorisation. This leads to faster, shorter, and easier to read code imo. – Paul Hiemstra Feb 10 '13 at 11:51
1

rnorm takes a vector for the mean parameter, which can be used to directly compute the matrix values:

Column-wise:

matrix(rnorm(n=50*10*length(mu), mean=rep(mu, each=50*10)), nrow=50)

Row-wize:

matrix(rnorm(n=50*10*length(mu), mean=rep(mu, each=10)), nrow=50, byrow=TRUE)
Matthew Lundberg
  • 42,009
  • 6
  • 90
  • 112