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

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

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)

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

Related

Segmenting a list of data; python

I am trying to write a code that takes a list flow_rate, changes it into a segmented list list_segmented of length segment_len. Then with that segmented list, I take each index and make it a list of data_segment.
I am getting stuck trying to figure out how to make each list_segmented[i] = data_segment. The last part of the code calls another function for data_segment in which I have previously written and can import it.
Appreciate your help.
def flow_rate_to_disorder_status(flow_rate,segment_len,interval,threshold):
inlist = flow_rate[:]
list_segmented = []
disorder_status = []
while inlist:
list_segmented.append(inlist[0 : segment_len])
inlist[0 : segment_len] = []
for i in range(0, len(list_segmented)):
data_segment = list_segmented[i]
condition = sym.has_symptom(data_segment, interval, threshold)
disorder_status.append(condition)
Initial function:
def has_symptom(data_segment,interval,threshold):
max_ratio = 1 # maximum ratio allowed when dividing
# data points in interval by len data_segment
# for our example it is 1
# NOTE: max_ratio can NOT be less than threshold
# to define the range of the given interval:
min_interval = interval[0]
max_interval = interval[1]
# create an empty list to add to data points that fall in the interval
symptom_yes = []
# create a loop function to read every point in data_segment
# and compare wether or not it falls in the interval
for i in range(0, len(data_segment)):
if min_interval <= data_segment[i] <= max_interval:
# if the data falls in interval, add it to list symptom_yes
symptom_yes.append(data_segment[i])
# to get the fraction ration between interval points and total data points
fraction_ratio = len(symptom_yes) / len(data_segment)
# if the ratio of data points that fall in interval to total points in
# data segments is more than or equal to threshold and less than or equal
# to max_ratio (1 in our case) then apply condition
if threshold <= fraction_ratio <= max_ratio:
condition = True # entire segment has the symptom
else:
condition = False # entire segment does NOT have the symptom
return condition
You nearly did it:
for i in range(0, len(data_segment)): # <-- looping thru data_segment
# data_segment = list_segmented[i] <-- this was back to front.
list_segmented[i] = data_segment # <-- this will work
note: there are cleaner ways of doing this in python (like list comprehension).
Anyway, good question. Hope that helps.
It looks like the lines
condition = sym.has_symptom(data_segment, interval, threshold)
disorder_status.append(condition)
should each be indented by one more level to be inside the for loop, so that they are executed for each data segment.
You presumably also want to return disorder_status at the end of the function.

How to make function that calculates moving average of a list?

I am trying to calculate a moving average of a list called 'temp_data' in the function below. The moving average data should be stored in a list called 'moving_average'. The code below works in the sense that list 'temp_mov' is printed inside the function (line 12), but not when I call the function later on (in the last line of the code). In that case, I get an empty list. What mistake do I make?
# calculate moving average of a list of weather data
def make_moving(temps, temp_mov):
''' Create moving average from list weather data'''
cumsum, temp_mov = [0], []
for i, x in enumerate(temps, 1):
cumsum.append(cumsum[i-1] + x)
if i>=N:
moving_ave = round((cumsum[i] - cumsum[i-N])/N, 1)
temp_mov.append(moving_ave)
print(temp_mov)
return temp_mov
make_moving(temp_data, moving_average)
print(moving_average)
You assign a new list to temp_mov here:
cumsum, temp_mov = [0], []
Therefore, moving_average is not updated when temp_mov changes.
Changing make_moving(temp_data, moving_average) to moving_average = make_moving(temp_data) and removing the temp_mov parameter will solve the problem.

Python second loop not detected

I am using python and some arcpy modules (that I do not think are important for my question) to run a code containing three iterations (a loop with two smaller loops inside). My code looks like this:
file = r"C:Directory\File"
cursor = arcpy.SearchCursor(file,fields)
A = range(1,270)
os.chdir ('C:\Directory')
book = xlwt.Workbook()
sheet1 = book.add_sheet('Sheet1',cell_overwrite_ok = True)
for a in A:
tot = 0
result = 0
for row in cursor:
if row.getValue('Firstfield') == a:
tot = tot + row.getValue('secondfield')
print (tot)
for row in cursor:
print row.getValue('GTYS_Branc')
if row.getValue('GTYS_Branc') == a:
result= result + row.getValue(Field1) * ((row.getValue(Field2))/tot )
sheet1.write((branch-1),0,finalIIIprob)
sheet1.write((a-1),1,result)
book.save('Excel.xls')
The code works but does not give me the results I want. I noticed that the problem is that it practically ignores the second internal loop and every iteration of the first internal loop after the first one. What could the problem be?
The issue may be that you are iterating over values in an "array", but there is nothing in there but one number which is A, not all the numbers from 0 to A, what you need to do is use range function:
try for i in range(A):

Grabbing values of an array in sets of 100

In the code below, ids is an array which contains the steam64 ids of all users in your friendslist. Now according to the steam web api documentation, GetPlayerSummaries only takes a list of 100 comma separated steam64 ids. Some users have more than 100 friends, and instead of running a for loop 200 times that each time calls the API, I want to take array in sets of 100 steam ids. What would be the most efficient way to do this (in terms of speed)?
I know that I can do ids[0:100] to grab the first 100 elements of an array, but how I accomplish doing this for a friendlist of say 230 users?
def getDescriptions(ids):
sids = ','.join(map(str, ids))
r = requests.get('http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key='+API_KEY+'&steamids=' + sids)
data = r.json();
...
Utilizing the code from this answer, you are able to break this into groups of 100 (or less for the last loop) of friends.
def chunkit(lst, n):
newn = int(len(lst)/n)
for i in xrange(0, n-1):
yield lst[i*newn:i*newn+newn]
yield lst[n*newn-newn:]
def getDescriptions(ids):
friends = chunkit(ids, 3)
while (True):
try:
fids = friends.next()
sids = ','.join(map(str, fids))
r = requests.get('http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key='+API_KEY+'&steamids=' + sids)
data = r.json()
# Do something with the data variable
except StopIteration:
break
This will create iterators broken into 3 (second parameter to chunkit) groups. I chose 3, because the base size of the friends list is 250. You can get more (rules from this post), but it is a safe place to start. You can fine tune that value as you need.
Utilizing this method, your data value will be overwritten each loop. Make sure you do something with it at the place indicated.
I have an easy alternative, just reduce your list size on each while/loop until exhaustion:
def getDescriptions(ids):
sids = ','.join(map(str, ids))
sids_queue = sids.split(',')
data = []
while len(sids_queue) != 0:
r = requests.get('http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key='+ \
API_KEY+'&steamids=' + ','.join(sids_queue[:100])
data.append(r.json) # r.json without (), by the way
# then skip [0:100] and reassign to sids_queue, you get the idea
sids_queue = sids_queue[101:]

Python Min-Max Function - List as argument to return min and max element

Question: write a program which first defines functions minFromList(list) and maxFromList(list). Program should initialize an empty list and then prompt user for an integer and keep prompting for integers, adding each integer to the list, until the user enters a single period character. Program should than call minFromList and maxFromList with the list of integers as an argument and print the results returned by the function calls.
I can't figure out how to get the min and max returned from each function separately. And now I've added extra code so I'm totally lost. Anything helps! Thanks!
What I have so far:
def minFromList(list)
texts = []
while (text != -1):
texts.append(text)
high = max(texts)
return texts
def maxFromList(list)
texts []
while (text != -1):
texts.append(text)
low = min(texts)
return texts
text = raw_input("Enter an integer (period to end): ")
list = []
while text != '.':
textInt = int(text)
list.append(textInt)
text = raw_input("Enter an integer (period to end): ")
print "The lowest number entered was: " , minFromList(list)
print "The highest number entered was: " , maxFromList(list)
I think the part of the assignment that might have confused you was about initializing an empty list and where to do it. Your main body that collects data is good and does what it should. But you ended up doing too much with your max and min functions. Again a misleading part was that assignment is that it suggested you write a custom routine for these functions even though max() and min() exist in python and return exactly what you need.
Its another story if you are required to write your own max and min, and are not permitted to use the built in functions. At that point you would need to loop over each value in the list and track the biggest or smallest. Then return the final value.
Without directly giving you too much of the specific answer, here are some individual examples of the parts you may need...
# looping over the items in a list
value = 1
for item in aList:
if item == value:
print "value is 1!"
# basic function with arguments and a return value
def aFunc(start):
end = start + 1
return end
print aFunc(1)
# result: 2
# some useful comparison operators
print 1 > 2 # False
print 2 > 1 # True
That should hopefully be enough general information for you to piece together your custom min and max functions. While there are some more advanced and efficient ways to do min and max, I think to start out, a simple for loop over the list would be easiest.

Categories

Resources