Reputation: 3
I know there may be more elegant to do this - but right now I just want to grok this logic...
My problem is that when I do a typical Y[t]=Y[t-1]+i[t]
thing for simulation it does not work when put in a function.
I want to have a data frame out with the correct variable value on each row for time or t 1-10.
Now the cat inside the loop reveals I am going wrong.
Here is my code:
iter <- 10; i <- rep(0.1,iter);
i <- c(0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0)
Y0 <- 0.25 ; O0 <- 4.16
Y <- rep(0,iter); O <- rep(0,iter)
Tot <- rep(0,iter)
t <- seq(1,iter) #start time and fill vector
Y[1]=Y0 #First iter
O[1]=O0
Tot[1]= Y0+O0
time<-rep(1,iter)#runtime unit
#This is a simplified version of the ICBM function, to test the logic and output
Isim <- function(i, h, Y0, O0,iter,time) {
for (t in 2:iter) {
time<- time+1
Y[t]=(Y[t-1]+i[t-1]); O[t]=(O[t-1]+i[t-1]); Tot[t]=Y[t]+O[t];
simout <- data.frame(i,Y0,O0,Y,O,Tot,time)
cat(time)
}
return(simout)
}
result <- Isim(i, h, Y0, O0,iter, time)
Upvotes: 0
Views: 96
Reputation: 89097
(Let's make abstraction of the fact your code cannot run.) You have a scoping issue at the Y[t]=(Y[t-1]+i[t-1])
step. Let's look at a small reproducible example:
increment_a <- function() { a <- a + 1; print(a); }
a <- 0; print(a); increment_a(); print(a);
# [1] 0 # ok
# [1] 1 # ok
# [1] 0 # not what you expected
Inside increment_a
, when R computes a + 1
, it first looks for a
in the function's environment. That environment being empty, it then looks for a
in the environment from which the function was called: your global environment. It finds it there, with a value of 0
. It adds 1
to that 0
and then goes to assign it (the a <-
part of the statement) in the local environment, i.e. the function's environment.
How can you solve this? You could tell R to assign the result of a + 1
to the a
found in the global environment: use <<-
instead of <-
:
increment_a <- function() { a <<- a + 1; print(a); }
a <- 0; print(a); increment_a(); print(a);
# [1] 0
# [1] 1
# [1] 1
BUT this is not recommended. It is dangerous and will cause you troubles down the line. Instead, you need to fully embrace the functional programming style. I suggest you read the first paragraph of http://en.wikipedia.org/wiki/Functional_programming, especially the part about functions not having side effects. This is how things work:
return
statement.<<-
.increment <- function(x) { x <- x + 1; print(x); return(x); }
a <- 0; print(a); a <- increment(a); print(a);
# [1] 0
# [1] 1
# [1] 1
Upvotes: 1
Reputation: 13122
In your loop, instead of time<- time+1
, try to use time[t] <- t
..
When you increment time
by 1
in each iteration, you end with the vector:
time
[1] 10 10 10 10 10 10 10 10 10 10
which is the final input in simout
.
simout$time
is altered in each iteration as follows:
2 2 2 2 ...
3 3 3 3 ...
...
10 10 10 ...
so you should change only a specific element of time
in each iteration.
Now (you can see it from cat
) simout$time
changes as:
1 1 1 1 ...
1 2 1 1 ...
1 2 3 1 ...
...
1 2 3 4 5 6 7 8 9 10 #this is the final input in "simout"
Upvotes: 0