Reputation: 1519
I think my question is very very easy for common R users.
Edit: My example is probably a to simplified version of my true problem: See the following code:
library(markovchain)
#create a new MC with transition matrix transitionMatrix
mcStaticPool <- new("markovchain", states=c("perf", "def", "prep"),
transitionMatrix=matrix(data=c(0.89715, 0.01475, 0.08810, 0, 1, 0, 0, 0, 1),
byrow=TRUE, nrow=3), name="StaticPool")
#display transition matrix
#print(mcStaticPool)
show(mcStaticPool)
#initially all loans are performing
initialState<-c(1,0,0)
nYears<-10
for(i in 1:nYears){
afterNYears<-initialState*(mcStaticPool^i)
print(afterNYears)
}
I want this in a vector. And actually only the numbers. not the states.
perf def prep
[1,] 0.89715 0.01475 0.0881
perf def prep
[1,] 0.8048781 0.02798296 0.1671389
perf def prep
[1,] 0.7220964 0.03985491 0.2380487
perf def prep
[1,] 0.6478288 0.05050584 0.3016654
perf def prep
[1,] 0.5811996 0.06006131 0.3587391
perf def prep
[1,] 0.5214232 0.06863401 0.4099428
perf def prep
[1,] 0.4677948 0.076325 0.4558802
perf def prep
[1,] 0.4196821 0.08322497 0.4970929
perf def prep
[1,] 0.3765178 0.08941528 0.5340669
perf def prep
[1,] 0.337793 0.09496892 0.5672381
The following loop:
for(i in 1:10){
test<-2*(2^i)
print(test)
}
This gives:
[1] 4
[1] 8
[1] 16
[1] 32
[1] 64
[1] 128
[1] 256
[1] 512
[1] 1024
[1] 2048
I want to save this as a variable, for example called test2.
I tried this:
for(i in 1:10){
test<-2*(2^i)
test2 <- print(test)
}
But then it gives:
> test2
[1] 2048
But I want the entire sequence in test2:
[1] 4
[1] 8
[1] 16
[1] 32
[1] 64
[1] 128
[1] 256
[1] 512
[1] 1024
[1] 2048
Thanks, Best regards,
Tim
Upvotes: 0
Views: 222
Reputation: 49660
As others have mentioned, you can just vectorize this, but if you are doing something more complicated that does not vectorize like this then there are other options.
When your main goal is to create a vector (or matrix or array) based on the result of each iteration then it is usually better/simpler/clearer/etc. to use the sapply function (or other related functions) rather than an explicit loop.
for example:
test2 <- sapply(2:11, function(x) 2*(2^i))
If you really need a loop then it is best to preallocate a vector (or matrix, array, list, etc.) and assign into the vector (or other structure).
Here is some benchmarking to compare the methods (I have increased the iterations to make the difference clearer):
> library(microbenchmark)
>
> out <- microbenchmark(
+ bad={test2 <- NULL; for(i in 1:10000) test2 <- c(test2,2*(2^i))},
+ good={test2 <- numeric(10000); for(i in 1:10000) test2[i] <- 2*(2^i) },
+ better={test2=sapply(1:10000, function(x) 2*(2^x))},
+ best={test2=2*(2^(1:10000))} )
> out
Unit: microseconds
expr min lq median uq max neval
bad 172508.454 174738.8165 176630.910 197765.369 211581.875 100
good 26387.491 27683.0960 28150.475 28567.769 52588.194 100
better 20645.118 21288.8155 22140.853 23022.652 49513.799 100
best 719.234 763.1595 768.086 773.628 1622.381 100
> plot(out)
>
Upvotes: 1
Reputation: 51680
General rule: if you find yourself using a for
loop in R you are most likely on the wrong route ;)
Vectorize when possible
test <- 2^2:11
If you insist in using a for
loop you should do
test <- NULL
for (i in 2:11)
test <- c(test, 2^i)
or, to avoid allocating memory each time
test <- numeric(10)
for (i in 1:10)
test[i] <- 2^(i+1)
Your code ends up with only the 2048 value as you are overwriting test each time with a single value, and not concatenating the other powers of 2 as you go.
Upvotes: 1
Reputation: 8488
You should simply do this:
test2 <- 2^(2:11)
or test2 <- 2*2^(1:10)
or test2 <- 2^(1:10+1)
, whichever shows better what you're trying to do.
But if you really want to use a loop, do this:
test2 <- numeric(10)
for(i in 1:length(test2)) {
test2[i] <- 2*(2^i)
}
Upvotes: 2