0

I am currently working my way through the book 'R for Data Science'.

I am trying to solve this exercise question (21.2.1 Q1.4) but have not been able to determine the correct output before starting the for loop.

Write a for loop to: Generate 10 random normals for each of μ= −10, 0, 10 and 100.

Like the previous questions in the book I have been trying to insert into a vector output but for this example, it appears I need the output to be a data frame?

This is my code so far:

values <- c(-10,0,10,100)
output <- vector("double", 10)

for (i in seq_along(values)) {
  output[[i]] <- rnorm(10, mean = values[[i]])
} 

I know the output is wrong but am unsure how to create the format I need here. Any help much appreciated. Thanks!

3
  • You can use lapply or sapply i.e. d1 <- data.frame(lapply(values, function(x) rnorm(10, mean=x))); colnames(d1) <- paste0("V", seq_along(values)) Commented Jan 27, 2017 at 8:50
  • Hi, thanks for your solution. That does work but it would be good to also get a for loop solution as this is a skill I am aiming to improve currently. Thanks! Commented Jan 27, 2017 at 9:00
  • You create an empty matrix or list first and then assign the values to it. i.e. output <- vector("list", 4); and use your code and cbind or rbind if necessary i.e. do.call(cbind, output) Commented Jan 27, 2017 at 9:02

3 Answers 3

7

There are many ways of doing this. Here is one. See inline comments.

set.seed(357) # to make things reproducible, set random seed

N <- 10 # number of loops

xy <- vector("list", N) # create an empty list into which values are to be filled

# run the loop N times and on each loop...
for (i in 1:N) {
  # generate a data.frame with 4 columns, and add a random number into each one
  # random number depends on the mean specified
  xy[[i]] <- data.frame(um10 = rnorm(1, mean = -10),
                        u0 = rnorm(1, mean = 0),
                        u10 = rnorm(1,  mean = 10),
                        u100 = rnorm(1, mean = 100))
}

# result is a list of data.frames with 1 row and 4 columns

# you can bind them together into one data.frame using do.call
# rbind means they will be merged row-wise
xy <- do.call(rbind, xy)

         um10         u0       u10      u100
1  -11.241117 -0.5832050 10.394747 101.50421
2   -9.233200  0.3174604  9.900024 100.22703
3  -10.469015  0.4765213  9.088352  99.65822
4   -9.453259 -0.3272080 10.041090  99.72397
5  -10.593497  0.1764618 10.505760 101.00852
6  -10.935463  0.3845648  9.981747 100.05564
7  -11.447720  0.8477938  9.726617  99.12918
8  -11.373889 -0.3550321  9.806823  99.52711
9   -7.950092  0.5711058 10.162878 101.38218
10  -9.408727  0.5885065  9.471274 100.69328

Another way would be to pre-allocate a matrix, add in values and coerce it to a data.frame.

xy <- matrix(NA, nrow = N, ncol = 4)

for (i in 1:N) {
  xy[i, ] <- rnorm(4, mean = c(-10, 0, 10, 100))
}

# notice that i name the column names post festum
colnames(xy) <- c("um10", "u0", "u10", "u100")
xy <- as.data.frame(xy)
Sign up to request clarification or add additional context in comments.

Comments

1

As this is a learning question I will not provide the solution directly.

> values <- c(-10,0,10,100)
> for (i in seq_along(values)) {print(i)} # Checking we iterate by position
[1] 1
[1] 2
[1] 3
[1] 4
> output <- vector("double", 10) 
> output # Checking the place where the output will be
 [1] 0 0 0 0 0 0 0 0 0 0
> for (i in seq_along(values)) { # Testing the full code
+     output[[i]] <- rnorm(10, mean = values[[i]])
+ } 
Error in output[[i]] <- rnorm(10, mean = values[[i]]) : 
  more elements supplied than there are to replace

As you can see the error say there are more elements to put than space (each iteration generates 10 random numbers, (in total 40) and you only have 10 spaces. Consider using a data format that allows to store several values for each iteration. So that:

> output <- ??
> for (i in seq_along(values)) { # Testing the full code
+     output[[i]] <- rnorm(10, mean = values[[i]])
+ } 
> output # Should have length 4 and each element all the 10 values you created in the loop

2 Comments

Using akrun's answer above worked: output <- vector("list", 4). Is this what you would do? Thanks for the thorough explanation of the thought process involved! Very helpful!
Yes, or simply using a output <- list(). Could you choose an answer as the most helpful by clicking on the tick? This way the question is marked as solved :D
0
# set the number of rows
rows <- 10

# vector with the values
means <- c(-10,0,10,100)

# generating output matrix
output <- matrix(nrow = rows,
             ncol = 4)

# setting seed and looping through the number of rows
set.seed(222)
for (i in 1:rows){
  output[i,] <- rnorm(length(means),
                  mean=means)
}

#printing the output
output

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.