Nested "for" loops in R - r

I'm an R novice with what I hope is a simple question. I've got a couple of nested loops I'm running and can't seem to get the output that I'm expecting.
I want to keep track of the balance in the internal loop. Each iteration represents 1 year. At the end of 15 years, I want to write the final balance to InvTotal for each of 4 simulations.
My final output should be 3 vectors (1 for each investment) of length 4, showing the final cumulative value for each investment at the end of 4 simulations.
My code is below. Any assistance you could provide would be a huge help.
Thank you!
Investment1_Balance <- 10000
Investment2_Balance <- 10000
Investment3_Balance <- 10000
Inv1Returns <- c(0, 1000, -500, 500)
Inv2Returns <- c(0, -9000, 30000, 10000)
Inv3Returns <- c(0, 4000, -1000, -2000)
Inv1Outcome = NULL
Inv2Outcome = NULL
Inv3Outcome = NULL
Inv1Total = NULL
Inv2Total = NULL
Inv3Total = NULL
random = NULL
for (j in 1:4)
{
for (i in 1:15 )
{
random[i] = runif(1, 0, 1)
Inv1Outcome[i] = if (random[i] <= .25){Investment1_Balance + Inv1Returns[1]}
else if (random[i] > .25 & random[i] <= .50){Investment1_Balance + Inv1Returns[2]}
else if (random[i] > .50 & random[i] <= .75){Investment1_Balance + Inv1Returns[3]}
else {Investment1_Balance + Inv1Returns[4]}
Inv2Outcome[i] = if (random[i] <= .20){Investment2_Balance + Inv2Returns[1]}
else if (random[i] > .20 & random[i] <= .30){Investment2_Balance + Inv2Returns[2]}
else if (random[i] > .30 & random[i] <= .70){Investment2_Balance + Inv2Returns[3]}
else ({Investment2_Balance + Inv2Returns[4]})
Inv3Outcome[i] = if (random[i] <= .50){Investment3_Balance + Inv3Returns[1]}
else if (random[i] > .50 & random[i] <= .70){Investment3_Balance + Inv3Returns[2]}
else if (random[i] > .70 & random[i] <= .90){Investment3_Balance + Inv3Returns[3]}
else ({Investment3_Balance + Inv3Returns[4]})
Investment1_Balance[i] =+ Inv1Outcome[i]
Investment2_Balance[i] =+ Inv2Outcome[i]
Investment3_Balance[i] =+ Inv3Outcome[i]
}
Inv1Total[j] = Investment1_Balance[15]
Inv2Total[j] = Investment2_Balance[15]
Inv3Total[j] = Investment3_Balance[15]
}
Inv1Total
Inv2Total
Inv3Total

Welcome to stackoverflow! There are a couple of points that you should consider while trying to figure out why your code isn't working as expected:
"Start small" : In your case here, I would start with one investment, maybe even with one simulation. This would verify if the logic of the calculation is fine, without distracting myself with other numbers.
"Seeing is believing" : Try to print intermediate results, so you can trace the calculation bugs.
Applying the previous, a first debugging would would look something like:
Investment1_Balance <- 10000
Inv1Returns <- c(0, 1000, -500, 500)
Inv1Outcome = NULL
Inv1Total = NULL
random = NULL
for (j in 1:4) { # Loop over simulations
cat("\n\n\nSimulation ", j, ": Investment balance:" , Investment1_Balance)
for (i in 1:15) { # Loop over years
random[i] = runif(1, 0, 1)
Inv1Outcome[i] = if (random[i] <= .25){Investment1_Balance + Inv1Returns[1]}
else if (random[i] > .25 & random[i] <= .50){Investment1_Balance + Inv1Returns[2]}
else if (random[i] > .50 & random[i] <= .75){Investment1_Balance + Inv1Returns[3]}
else {Investment1_Balance + Inv1Returns[4]}
Investment1_Balance[i] =+ Inv1Outcome[i]
cat("\n Year: ", i, "- Outcome:", Inv1Outcome[i], "- Final balance: " , Investment1_Balance[i])
}
Inv1Total[j] = Investment1_Balance[15]
}
Inv1Total
.
You can see a couple of problems with the numbers printed :
The outcome is always the same as the balance. This suggests that there might be a problem with the addition.
Let's try to debug that:
> x = 10
> x =+ 2
> x
[1] 2
Apparently, the =+ isn't working as expected. So we have to correct that : Investment1_Balance[i+1] = Investment1_Balance[i] + Inv1Outcome[i]
.
When printing the initial investment balance for each simulation, we can see that the first simulation is fine (Simulation 1 : Investment balance: 10000). But for the other simulations we get (Simulation 2 : Investment balance: 10000 9500 10000 10000 10500 11000 9500 11000 10000 10500 10500 10000 10000 11000 11000).
This suggests a problem with the initialization. Each simulation takes the output of the previous and starts with it. The logic of that is not quite correct. The simple solution would be resetting Investment1_Balance <- 10000 at the beginning of each simulation. It would even make sense in this case to reset all the Balance and Outcome variables.
.
Here is the new code after debugging :
Inv1Returns <- c(0, 1000, -500, 500)
random = NULL
Inv1Total = NULL
for (j in 1:4) { # Loop over simulations
Investment1_Balance <- 10000
Inv1Outcome = NULL
cat("\n\n\nSimulation ", j, ": Investment balance:" , Investment1_Balance)
for (i in 1:15) { # Loop over years
random[i] = runif(1, 0, 1)
Inv1Outcome[i] = if (random[i] <= .25){Investment1_Balance + Inv1Returns[1]}
else if (random[i] > .25 & random[i] <= .50){Investment1_Balance + Inv1Returns[2]}
else if (random[i] > .50 & random[i] <= .75){Investment1_Balance + Inv1Returns[3]}
else {Investment1_Balance + Inv1Returns[4]}
Investment1_Balance[i+1] = Investment1_Balance[i] + Inv1Outcome[i]
cat("\n Year: ", i, "- Outcome:", Inv1Outcome[i], "- Final balance: " , Investment1_Balance[i])
}
Inv1Total[j] = Investment1_Balance[15]
}
Inv1Total
Check if the output is now correct. If so, you can go ahead and add Inv2 and Inv3 as well.

Related

Guessing game in R

I've tried to create a guessing game in R but it gives me the error with "readinteger". Just started learning R, sorry if it's a too simple question. The idea of the game is to ask a user to choose a random integer from 0 to 10 and if he guesses say something "well done" and if he does not say something like "It's bigger" or "It's smaller" until he guesses the integer.
> num <- round(runif(1) * 10, digits = 0)
> guess <- -1
>
> cat("Guess an integer between 0 and 10.n")
Guess an integer between 0 and 10.n>
> while(guess != num)
+ {
+ guess = readinteger()
+ if (guess == num)
+ {
+ cat("Well done,", num, "is correct.n")
+ }
+ else if (guess < num)
+ {
+ cat("It's bigger!n")
+ }
+ else if(guess > num)
+ {
+ cat("It's smaller!n")
+ }
+ }
Error in readinteger() : could not find function "readinteger"
Maybe you want readline()? I'm guessing you want this. You need to define that function in your script.
readinteger <- function() {
n <- readline(prompt="Enter an integer: ")
return(as.integer(n))
}
num <- round(runif(1) * 10, digits = 0)
guess <- -1
...

Trying to call a function 1000 times with replicate

simulate <- function(bankroll, bet, max_iterations) { #gambler's ruin function
iteration = 1
while (bankroll > 0 & iteration < max_iterations) {
win <- sample(0:1, size = 1) #either loos or win
if (win) {
bankroll <- (bankroll + bet)
} else {
bankroll <- (bankroll - bet)
}
iteration <- iteration + 1
}
return(list(c(iteration, bankroll)))
}
simulate(1000, 100, 100)
I am trying to call the above function 1000 times to get the vector. Then I need to count how many of the iterations were less than 100. Any suggestion? Thanks
This can simply be reduced to:
simulate <- function(bankroll, bet, max_iterations){
bankroll + bet * sum(sample(c(-1, 1), max_iterations, TRUE))
}
Then you could do:
sum(replicate(1000, simulate(1000, 100, 100))<100)
This is a simple version using base
simulate <- function(bankroll, bet, max_iterations) { #gambler's ruin function
iteration = 1
while (bankroll > 0 & iteration < max_iterations) {
win <- sample(0:1, size = 1) #either loos or win
if (win) {
bankroll <- (bankroll + bet)
} else {
bankroll <- (bankroll - bet)
}
iteration <- iteration + 1
}
return(bankroll)
}
calls <- replicate(n = 1000,expr = simulate(1000, 100, 100))
calls_less_100 <- calls < 100
result <- length(calls[calls_less_100])
result
probability <- result/length(calls)
probability

Having syntax errors with if statements

I have the following question:
In the imported data frame, I need to create a new column named “profit_margin_flag” whose value is computed as follows [profit margin = Profit / Sales].
a.If the profit margin is negative, the new column should have the value “negative”.
b.If the profit margin is positive and less than 10%, the new column should have the value “low margin”.
c.If the profit margin is 10% or more, but less than 25%, the new column should have the value “standard margin”.
d.If the profit margin is 50% or more, the new column should have the value “high margin”.
I coded this:
orders$profit_margin_flag <- orders$Profit/orders$Sales
n <- nrow(orders)
`for (i in (1:n))`
{
if(orders$profit_margin_flag[i] < 0)
{orders$profit_margin_flag[i] <- "negative"}
else if(orders$profit_margin_flag[i] >0 && <.10)
{orders$profit_margin_flag[i]<- "low margin"}
else if(orders$profit_margin_flag[i] >= .10 && < .25)
{orders$profit_margin_flag[i]<- "standard margin"}
else if(orders$profit_margin_flag[i] >= .50)
{orders$profit_margin_flag[i]<- "high margin"}
}
I receive this error:
else if(orders$profit_margin_flag[i] >0 && <.10)
#Error: unexpected 'else' in " else"
# {
+ orders$profit_margin_flag[i]<- "low margin"
+ }
else if(orders$profit_margin_flag[i] >= .10 && < .25)
Error: unexpected 'else' in "else"
{orders$profit_margin_flag[i]<- "standard margin"}
else if(orders$profit_margin_flag[i] >= .50)
Error: unexpected 'else' in " else"
{orders$profit_margin_flag[i]<- "high margin"}
}
Error: unexpected '}' in "}"
As #mickey pointed out, && < .10 isn't valid syntax.
That being said, do you want to replace profit_margin_flag's value with "negative" etc. (as you specific in the OP) or do you want it assigned to a new variable?
I cleaned up your code a little bit (with the flag being assigned to a new variable profit_margin_flag and the margin values originally being stored in profit_margin) and this should work.
orders <- data.frame(profit_margin = c(-2, 0.07, 0.14, 11), profit_margin_flag = rep_len(NA, 4))
for(i in 1:nrow(orders)){
+ if(orders$profit_margin[i] < 0){
+ orders$profit_margin_flag[i] <- "negative"
+ }
+ else if(orders$profit_margin[i] > 0 && orders$profit_margin[i] < 0.10){
+ orders$profit_margin_flag[i]<- "low margin"
+ }
+ else if(orders$profit_margin[i] >= 0.10 && orders$profit_margin[i] < 0.25)
+ {
+ orders$profit_margin_flag[i]<- "standard margin"
+ }
+ else if(orders$profit_margin[i] >= 0.50)
+ {
+ orders$profit_margin_flag[i]<- "high margin"
+ }
+ }
orders
# profit_margin profit_margin_flag
# 1 -2.00 negative
# 2 0.07 low margin
# 3 0.14 standard margin
# 4 11.00 high margin

If & ifelse statement in R

As the new user in R, I met few problems when I tried to evaluate a.
Code:
// time2 are numbers //
a = d3$Time2
b = c(...)
for (i in 1:65){
for (j in 1:1762){
if( (a[j]>=1474161415+900*(i-1))&(a[j]<1474161415+900*i) ){ a[j] = b[j] }
}
}
Results:
Error in if ((a[j] >= 1474161415 + 900 * (i - 1)) & (a[j] < 1474161415 + :
missing value where TRUE/FALSE needed
Also I have tried:
ifelse( ((a[j]>=1474161415+900*(i-1)) & (a[j]<1474161415+900*i)) , a[j]=b[j])
Results:
-unexpected '=' in -ifelse( ((a[j]-=1474161415+900-(i-1)) &
(a[j]-1474161415+900-i)) , a[j]=--

MATLAB to R Conversion: Append values to an existing empty array through for loop

I have the below code with me. This code was written originally in MATLAB. I have two questions here:
1) What would be the corresponding command in R for the below command in MATLAB:
duet(i).p = [];
2) In the below code I am getting all the correct 6 values for duet$n, but I am not getting correct values for duet$p. My question is how to append the values to an empty existing array duet$p[i] in R through the for loop iterations.
This line is not working in the below code:
duet$p[i] <- c(duet$p[i],j)
I might also have declared duet$p[i] <- array() incorrectly.
The values for duet.n and duet.p from MATLAB are:
duet.n
2 0 2 0 1 3
duet.p
[] [3,6] [] [1,3,5,6] [1,6] []
In R, I am getting duet$n values correctly, but I am not able to get the array kind of results for duet$p.
Any help to get the duet$p values would be appreciated.
x <- matrix(c(-1,2,4,1,7,4.2,3,0,1.2,-1.2,5.1,4,2,3.1,1.1,1,1,9,0,1,2,2,8,1,2,2,2,2,2,2),nrow=6,ncol=5,byrow=T)
fro=1;N=6;M=2;V=3;
F <- list(f=c())
duet = list()
for (i = 1 : N){
duet$n[i] = 0
duet$p[i] = array() ## Create an empty array
for (j in 1 : N){
dl = 0
de = 0
dm = 0
for (k = 1 : M){
if (x[i,V + k] < x[j,V + k]){
dl = dl + 1
} else if (x[i,V + k] == x[j,V + k]){
de = de + 1
} else{
dm = dm + 1
}
}
if (dl == 0 & de != M){
duet$n[i] = duet$n[i] + 1
} else if (dm == 0 & de != M){
duet$p[i] = c(duet$p[i],j)
}
}
if (duet$n[i] == 0){
x[i,6] = 1
F$f = c(F$f,i)
}
}
This appears to get the output you want:
x <- matrix(c(-1,2,4,1,7,4.2,3,0,1.2,-1.2,5.1,4,2,3.1,1.1,1,1,9,0,1,2,2,8,1,2,2,2,2,2,2),nrow=6,ncol=5,byrow=T)
fro=1;N=6;M=2;V=3;
F <- list(f=c())
duet = list(n=rep(0,N), p=lapply(1:N, function(x)c()))
for (i in 1 : N){
duet$n[i] = 0
#duet$p[[i]] = c() ## Create an empty array
#if(i==2) browser()
for (j in 1 : N){
k=1:M
dl <- sum(x[i,V + k] < x[j,V + k])
de <- sum(x[i,V + k] == x[j,V + k])
dm <- sum(x[i,V + k] > x[j,V + k])
if (dl == 0 & de != M){
duet$n[i] = duet$n[i] + 1
} else if (dm == 0 & de != M){
duet$p[[i]] = c(duet$p[[i]],j)
}
}
if (duet$n[i] == 0){
#x[i,6] = 1
F$f = c(F$f,i)
}
}
What have I done?
commented out the line x[i,6] =1, because there isn't an x[i,6], and I'm not sure what you meant it to be. You will need to sort this out.
Initialised duet$n as a vector
Initialised duet$p as a list of n empty vectors
removed the k loop as conditional counting in R can be done as the sum of elements where the condition is TRUE.
corrected the syntax of for loops: = became in
I think you're trying to do duet[i]$p instead of what you're doing. Also you need to initialize each cell as a list

Resources