replicate function in R returns NULL
Asked Answered
Z

3

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 :)

Zischke answered 31/10, 2013 at 21:33 Comment(1)
Your expression returns the value NULL. It also, as a side effect, prints values to the console. But those are distinct actions.Mucilage
H
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
Hessler answered 31/10, 2013 at 22:43 Comment(2)
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?Zischke
Basically yes, but I prefer to think about nested function calls "from the inside out" so I would have reversed that sequence you constructed.Hessler
C
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.

Correlation answered 31/10, 2013 at 21:38 Comment(1)
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?Zischke
H
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
Hessler answered 31/10, 2013 at 22:43 Comment(2)
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?Zischke
Basically yes, but I prefer to think about nested function calls "from the inside out" so I would have reversed that sequence you constructed.Hessler
S
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())
Sealey answered 31/10, 2013 at 21:39 Comment(2)
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?Zischke
c is just the function c, see ?c. it combines values into a vector or listSealey

© 2022 - 2024 — McMap. All rights reserved.