Yungpythonnoob
Yungpythonnoob

Reputation: 125

How to make a nested for-loop with two individual loops?

I am tasked with running a for-loop which initially finds the value of funds in a mans investment account from his 41-65th birthday. Here is the code below.

mu = 0.076 ###Mean
sigma = 0.167 ###Standard deviation
np.exp(np.random.normal(mu, sigma,))


u = .076 ###set variables 
bi = 50000 ###set variables 

empty = [] ###empty list
for i in range(25): ###range for birthdays 40-65
    bi = ((bi) * (np.exp(np.random.normal(mu, sigma))))
    empty.append(bi)
print(empty)
len(empty) ##making sure my lists match up

roundedempty = [ '%.2f' % elem for elem in empty ]
    age = [41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,
                   60,61,62,63,64,65]
    len(age) ##making sure my lists match up
    investing = pd.DataFrame({"Balance":roundedempty, "Age":age})
    investing.set_index('Age', inplace=True)
    investing

When I print this out it give me this: 
Age   Balance           
41    53948.13
.........
65    334294.72

Now I am tasked with simulating this 100,000 times, but I am not sure how to nest another loop within that first set of code.

mu = 0.076 ###Mean
sigma = 0.167 ###Standard deviation
bi = 50000

lognormvals = np.zeros(100000)
for i in range(100000):
            lognormvals[i] = ((bi) * (np.exp(np.random.normal(mu, sigma,))))
print(lognormvals)
np.mean(lognormvals)

This is what I want, but it is only doing it for his 41st birthday. I am tasked with trying to find the means of each birthday from his 41-65th. How can I nest this loop within the first loop to solve this?

My Shot at solving:
def InvestmentSim():
    mu = 0.076 ###Mean
    sigma = 0.167 ###Standard deviation
    np.exp(np.random.normal(mu, sigma,))


    u = .076 ###set variables 
    bi = 50000 ###set variables 

    empty = [] ###empty list
    for i in range(25): ###range for birthdays 40-65
        bi = ((bi) * (np.exp(np.random.normal(mu, sigma))))
        empty.append(bi)

    roundedempty = [ '%.2f' % elem for elem in empty ]
    age = [41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,
                   60,61,62,63,64,65]
    len(age) ##making sure my lists match up
    investing = pd.DataFrame({"Balance":roundedempty, "Age":age})
    investing.set_index('Age', inplace=True)
    a = investing.iloc[24]['Balance']
    return a

def AverageSim(iterations):
    results = []
    for n in range (0, iterations):
        a = InvestmentSim()
        results.append(a)
        print(results)
    return myresult

myresult = AverageSim(1)
myresults = np.array(myresult) # Turn the list of values into an array
mean = np.mean(myresults)
median = np.median(myresults)
print(mean, median)

Instead of doing all the balance for each year instead I just singled out the balance on his 65th birthday and set it equal to (a). Is this how my code should work? Doesn't seem to be running

Upvotes: 1

Views: 126

Answers (2)

ikom
ikom

Reputation: 166

If you just want to repeat the first snippet n times, then I'd suggest wrappning your code for the simulation, up in a function which you can call repeatedly in a for loop. The function should return your expected values, and the for loop should collect the results. After the loop is finished you can do further calculations with the loop such as mean.

# Your simulation as a callable function
def InvestmentSim():
    # your first code
    return investing


def AverageSims(iterations):

    # Initialise an empty list to collect the results
    results = []

    for n in range (0, iterations):
        investing = InvestmentSim()
        results.append(investing)
        # Adds investing to the end of the list

    # Returns a list of all the dataframes which you can use for future
    # calculations.
    # Or do the desired calculations here and return only those results.
    return results

myresult = AverageSims(100000)

Note that with 100,000 iterations you will get a very long list of fairly bulky dataframes. So instead you may want to do some calculations in place or pull out relevant results from each iteration and discard the rest. For example you could just save the start and end balances from each sim and append those to lists and return those. I'd give an example but I don't use pandas so I don't want to guess at the syntax. The basic principle is the same though: Initialise some blank lists and append the results in the for loop. Calculations will probably be simpler to set up if you turn the finished list(s) into numpy arrays using np.array(somelist)

Edit

Your code isn't running because you're calling the AverageSims function inside the AverageSims function, so you never actually get to that call. You need to move that call outside so it's executed when you run your script. The simplest way is to write the call the same way I did above, outside any function and without indentation.

Also, if your AverageSims() function doesn't have the return mysresults line, it will return None instead. That's not a problem unless you want to use results later on. If you don't want to keep the results and are happy with printing them out as you do now, you can also call the function without equating it to a variable:

def InvestmentSim():
    # your first code
    return investing


def AverageSims(iterations):
    # Repeatedly do the simulation, collect results

    # Returning the results, if you don't need them you can omit this:
    return myresult


# Now call the AverageSims function, otherwise it will never be executed. Note: No indent.  
myresults = AverageSims(100000) # If you're returning the results
# OR:
AverageSims(100000) # If you don't return the results

myresult = np.array(myresult) # Turn the list of values into an array
mean = np.mean(myresult)
median = np.median(myresult)
print(mean, median)

Upvotes: 2

blues
blues

Reputation: 5185

You can just put a loop inside another loop:

for x in range(10):
    for y in range(5):
         print(x,y)

I your case it would also be advisable to put the inner loop into a function, and run that function in the outer loop. Like this:

def calculate(*args):
    # do your calculations here that include a loop
    return result

for x in range(100000):
    calculate()

Upvotes: 0

Related Questions