6

I am confused about the output from the replicate function in R, I am trying to use it in two different ways, that (in my mind) should give a matrix as output!

so, if I use

replicate(5, seq(1,5,1))

I get a matrix 5x5

    [,1] [,2] [,3] [,4] [,5]
[1,]    1    1    1    1    1
[2,]    2    2    2    2    2
[3,]    3    3    3    3    3
[4,]    4    4    4    4    4
[5,]    5    5    5    5    5

..and that's ok, I get that...

but, if I instead use:

replicate(5, for(i in 1:5){print(i)})

I get the following:

[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[[1]]
NULL

[[2]]
NULL

[[3]]
NULL

[[4]]
NULL

[[5]]
NULL

can anyone explain me why does this happen? thanks :)

IRTFM
  • 258,963
  • 21
  • 364
  • 487
TriRook
  • 147
  • 1
  • 3
  • 18
  • 4
    Your expression returns the value NULL. It also, as a side effect, prints values to the console. But those are distinct actions. – joran Oct 31 '13 at 21:38

3 Answers3

5

A for loop returns NULL. So in the second case, the replicate function is executing for(i in 1:5){print(i)} five times, which is why you see all those numbers printed out.

Then it is putting the return values in a list, so the return value of the replicate call is a list of five NULLs, which gets printed out. Executing

x<-replicate(5, for(i in 1:5){print(i)})
x

should clarify.

mrip
  • 14,913
  • 4
  • 40
  • 58
  • thanks for the answer. yes, I did actually try that before and noticed that `x` returns `NULL` but I am confused about why it does that. is that because `for` returns a list first (5 times 1-->5) and then it doesn't run so that the `replicate` has 5 `NULLs`? – TriRook Nov 01 '13 at 15:36
4

As @mrip says a for-loop returns NULL so you need to assign to an object within the loop, and return that object to replicate so it can be output. However, mrip's code still results in NULLs from each iteration of the replicate evaluation.

You also need to assign the output of replicate to a name, so it doesn't just evaporate, er, get garbage collected. That means you need to add the d as a separate statement so that the evaluation of the whole expression inside the curley-braces will return 'something' rather than NULL.

d <- numeric(5); res <- replicate(5, { 
                            for(i in 1:5){d[i] <- print(i)} ; d}
                                  )
[1] 1
[1] 2

snipped
[1] 4
[1] 5
> res
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    1    1    1    1
[2,]    2    2    2    2    2
[3,]    3    3    3    3    3
[4,]    4    4    4    4    4
[5,]    5    5    5    5    5
IRTFM
  • 258,963
  • 21
  • 364
  • 487
  • thanks for the explanation of the object. if I get it right, you assigned to `res` the `replicate` function, then the `for` loop assigns the output that has to be printed out to `d[i]` and then you visualize `d` that should be replicated 5 times, that's why you get the matrix...correct? – TriRook Nov 01 '13 at 15:40
  • Basically yes, but I prefer to think about nested function calls "from the inside out" so I would have reversed that sequence you constructed. – IRTFM Nov 01 '13 at 18:33
0

The for loop is giving a list back, while the seq() call is giving a vector back. This should give you the same as the seq() using a for loop

foo <- function(){
  b = list()
  for(i in 1:5) b[i] <- i
  do.call(c, b)
}

replicate(5, foo())
sckott
  • 5,755
  • 2
  • 26
  • 42
  • the function you wrote does work, looks like you used the `b[i] <- i` assignment similar to what @DWin did. I have one question tho, sorry if it's trivial, in the `do.call(c, b)`, I get what `b` is, but how about `c`? – TriRook Nov 01 '13 at 15:47
  • c is just the function `c`, see `?c`. it combines values into a vector or list – sckott Nov 01 '13 at 15:54