calculating a class avg from a file - python

For this function, I want the class average for each assignment. I get this error when I try to test my function. Can anyone please help me fix this?
I want to go through the columns and have something like this. After I split the list, I want to interleave the grades of the assignments and add the corresponding items. How do I do that and then calculate the average?
I want to have [99, 88, 77, 66][11, 22, 33, 44][78, 58, 68, 88]into [99, 11, 78][88, 22, 58][77, 33, 68][66, 44, 88]
for item in range(grades_list[4:]):
builtins.TypeError: 'list' object cannot be interpreted as an integer
Here is the file for my function.
Last Name,First Name,Student No.,uTORid,A1,A2,A3,A4
Smith, Joe,9911991199,smithjoe9,99,88,77,66
Ash, Wood,9912334456,ashwood,11,22,33,44
Full, Kare,9913243567,fullkare,78,58,68,88
def class_avg(open_file):
'''(file) -> list of float
Return a list of assignment averages for the entire class given the open
class file. The returned list should contain assignment averages in the
order listed in the given file. For example, if there are 3 assignments
per student, the returned list should 3 floats representing the 3
averages.
[a1_avg, a2_avg, a3_avg, a4_avg]
[62.666666666666664, 56.0, 59.333333333333336, 66.0]
'''
new_list = []
for line in open_file:
grades_list = line.split(',')
for item in range(grades_list[4:]):
total = sum(grades_list[4:][item])
avg = total/len(grades_list[4:])
new_list.append(avg)
return new_list

There are a couple problems in your code.
You need to skip the header line ("Last Name,First Name,Student No.,uTORid,A1,A2,A3,A4")
You're also calculating multiple averages per student (for the first row, your code essentially does (9 + 9) / 2, (8 + 8) / 2, etc)
Also, it seems like you are trying to read down the columns, but that doesn't work
Something like this might work for you:
averages = []
with open('class_avg.csv') as fp:
next(fp) # skip header row
reader = csv.reader(fp)
for student_row in reader:
grades = student_row[4:] # extract columns 4, 5, 6, and 7 all at once
total = sum(float(grade) for grade in grades)
average = total / len(grades)
averages.append(average)
print(averages)

Create a 2d list .....
Read all the lines and then just do computation on the colomns you want output for ...
Accessing the column is something like
#example in python console
>>> list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> new_list = [item[1] for item in list]
>>> new_list
[2, 5, 8]

Related

How to store data from text files into lists on integers [duplicate]

This question already has answers here:
How do I create variable variables?
(17 answers)
Closed 10 days ago.
Hi hope everyone is okay.
I am trying to find the most simple method to take data from a text file and store it into diffrent
variables. Below is the format of a text file:
TEXT FILE:
min:1,2,3,4,5,7,8,9
avg:1,2,3,4
max:1,2,3,4,5,1,2,3,44,55,32,12
I want to take each of these lines remove the part before the number starts (min,avg,max and the ':')
and store all the number data in seperate variables in their appropriate names.
NOTE: amount of numbers in each line may differ and shouldnt effect the code
desired in python:
min = [1,2,3,4,5,7,8,9]
avg = [1,2,3,4]
max = [1,2,3,4,5,1,2,3,44,55,32,12]
The code i have tried:
with open('input.txt', 'r') as input:
input = input.read()
input = input.strip().split(',')
After this part i am unsure which method would be best to achieve what I am trying to do.
Any help is appriciated!
There's no reasonable way to generate variables (by name) dynamically. Better to use a dictionary. Something like this:
my_dict = {}
with open('input.txt') as data:
for line in map(str.strip, data):
try:
key, vals = line.split(':')
my_dict[key.rstrip()] = list(map(int, vals.split(',')))
except ValueError:
pass
print(my_dict)
Output:
{'min': [1, 2, 3, 4, 5, 7, 8, 9], 'avg': [1, 2, 3, 4], 'max': [1, 2, 3, 4, 5, 1, 2, 3, 44, 55, 32, 12]}
Using exec for a string evaluation. Do that on trusted data to avoid injection attacks.
with open('input.txt', 'r') as fd:
data = fd.read()
# list of lines
lines = data.split('\n')
# python code format
code_format = '\n'.join("{} = [{}]".format(*line.partition(':')[::2]) for line in lines if line)
# execute the string as python code
exec(code_format)
print(avg)
#[1, 2, 3, 4]
Notice that there is a further side effect in this code evaluation since some variable identifiers overload those of the built-in functions min, max. So, if after the execution of the code you try to call such build-in functions you will get TypeError: 'list' object is not callable.
One way to re-approach the problem would be by pickling the objects and use pickle.dumps to save an object to a file and pickle.loads to retrieve the object, see doc.
This is how you store it in a python dictionary:
txtdict = {}
with open('input.txt', 'r') as f:
for line in f:
if line.strip():
name = line.split(':')[0]
txtdict[name] = [int(i) for j in line.strip().split(':')[1:] for i in j.split(',')]
Output:
{'min': [1, 2, 3, 4, 5, 7, 8, 9],
'avg': [1, 2, 3, 4],
'max': [1, 2, 3, 4, 5, 1, 2, 3, 44, 55, 32, 12]}

How can you find the maximum nth integer in a list in python? [duplicate]

I know how to find the 1st highest value but don't know the rest. Keep in mind i need to print the position of the 1st 2nd and 3rd highest value.Thank You and try to keep it simple as i have only been coding for 2 months. Also they can be joint ranks
def linearSearch(Fscore_list):
pos_list = []
target = (max(Fscore_list))
for i in range(len(Fscore_list)):
if Fscore_list[i] >= target:
pos_list.append(i)
return pos_list
This will create a list of the 3 largest items, and a list of the corresponding indices:
lst = [9,7,43,2,4,7,8,5,4]
values = []
values = zip(*sorted( [(x,i) for (i,x) in enumerate(f_test)],
reverse=True )[:3] )[0]
posns = []
posns = zip(*sorted( [(x,i) for (i,x) in enumerate(f_test)],
reverse=True )[:3] )[1]
Things are a bit more complicated if the same value can appear multiple times (this will show the highest position for a value):
lst = [9,7,43,2,4,7,8,5,4]
ranks = sorted( [(x,i) for (i,x) in enumerate(lst)], reverse=True
)
values = []
for x,i in ranks:
if x not in values:
values.append( x )
posns.append( i )
if len(values) == 3:
break
print zip( values, posns )
Use heapq.nlargest:
>>> import heapq
>>> [i
... for x, i
... in heapq.nlargest(
... 3,
... ((x, i) for i, x in enumerate((0,5,8,7,2,4,3,9,1))))]
[7, 2, 3]
Add all the values in the list to a set. This will ensure you have each value only once.
Sort the set.
Find the index of the top three values in the set in the original list.
Make sense?
Edit
thelist = [1, 45, 88, 1, 45, 88, 5, 2, 103, 103, 7, 8]
theset = frozenset(thelist)
theset = sorted(theset, reverse=True)
print('1st = ' + str(theset[0]) + ' at ' + str(thelist.index(theset[0])))
print('2nd = ' + str(theset[1]) + ' at ' + str(thelist.index(theset[1])))
print('3rd = ' + str(theset[2]) + ' at ' + str(thelist.index(theset[2])))
Edit
You still haven't told us how to handle 'joint winners' but looking at your responses to other answers I am guessing this might possibly be what you are trying to do, maybe? If this is not the output you want please give us an example of the output you are hoping to get.
thelist = [1, 45, 88, 1, 45, 88, 5, 2, 103, 103, 7, 8]
theset = frozenset(thelist)
theset = sorted(theset, reverse=True)
thedict = {}
for j in range(3):
positions = [i for i, x in enumerate(thelist) if x == theset[j]]
thedict[theset[j]] = positions
print('1st = ' + str(theset[0]) + ' at ' + str(thedict.get(theset[0])))
print('2nd = ' + str(theset[1]) + ' at ' + str(thedict.get(theset[1])))
print('3rd = ' + str(theset[2]) + ' at ' + str(thedict.get(theset[2])))
Output
1st = 103 at [8, 9]
2nd = 88 at [2, 5]
3rd = 45 at [1, 4]
BTW : What if all the values are the same (equal first) or for some other reason there is no third place? (or second place?). Do you need to protect against that? If you do then I'm sure you can work out appropriate safety shields to add to the code.
Jupyter image of the code working
This question was on my Udemy machine learning course way too soon. Scott Hunter helped me the most on this problem, but didn't get me to a pass on the site. Having to really think about the issue deeper on my own. Here is my solution, since couldn't find it anywhere else online--in terms that I understood everything that was going on*:
lst = [9,7,43,2,4,7,8,9,4]
ranks = sorted( [(x,i) for (i,x) in enumerate(lst)], reverse=True )
box = []
for x,i in ranks:
if i&x not in box:
box.append( x )
if len(box) == 3:
break
print(box)
So we have a list of numbers. To rank the numbers we sort the value with its position for every position that has a value when we enumerate/iterate the list. Then we put the highest values on top by reversing it. Now we need a box to put our information in to pull out of later, so we build that box []. Now for every value with a position put that in the box, if the value and position isn't already in the box--meaning if the value is already in the box, but the position isn't, still put in the box. And we only want three answers. Finally tell me what is in the variable called box.
*Many of these answers, on this post, will most likely work.
Input : [4, 5, 1, 2, 9]
N = 2
Output : [9, 5]
Input : [81, 52, 45, 10, 3, 2, 96]
N = 3
Output : [81, 96, 52]
# Python program to find N largest
# element from given list of integers
l = [1000,298,3579,100,200,-45,900]
n = 4
l.sort()
print(l[-n:])
Output:
[298, 900, 1000, 3579]
lst = [9,7,43,2,4,7,8,9,4]
temp1 = lst
print(temp1)
#First Highest value:
print(max(temp1))
temp1.remove(max(temp1))
#output: 43
# Second Highest value:
print(max(temp1))
temp1.remove(max(temp1))
#output: 9
# Third Highest Value:
print(max(temp1))
#output: 7
There's a complicated O(n) algorithm, but the simplest way is to sort it, which is O(n * log n), then take the top. The trickiest part here is to sort the data while keeping the indices information.
from operator import itemgetter
def find_top_n_indices(data, top=3):
indexed = enumerate(data) # create pairs [(0, v1), (1, v2)...]
sorted_data = sorted(indexed,
key=itemgetter(1), # sort pairs by value
reversed=True) # in reversed order
return [d[0] for d in sorted_data[:top]] # take first N indices
data = [5, 3, 6, 3, 7, 8, 2, 7, 9, 1]
print find_top_n_indices(data) # should be [8, 5, 4]
Similarly, it can be done with heapq.nlargest(), but still you need to pack the initial data into tuples and unpack afterwards.
To have a list filtered and returned in descending order with duplicates removed try using this function.
You can pass in how many descending values you want it to return as keyword argument.
Also a side note, if the keyword argument (ordered_nums_to_return) is greater than the length of the list, it will return the whole list in descending order. if you need it to raise an exception, you can add a check to the function. If no args is passed it will return the highest value, again you can change this behaviour if you need.
list_of_nums = [2, 4, 23, 7, 4, 1]
def find_highest_values(list_to_search, ordered_nums_to_return=None):
if ordered_nums_to_return:
return sorted(set(list_to_search), reverse=True)[0:ordered_nums_to_return]
return [sorted(list_to_search, reverse=True)[0]]
print find_highest_values(list_of_nums, ordered_nums_to_return=4)
If values can appear in your list repeatedly you can try this solution.
def search(Fscore_list, num=3):
l = Fscore_list
res = dict([(v, []) for v in sorted(set(l), reverse=True)[:num]])
for index, val in enumerate(l):
if val in res:
res[val].append(index)
return sorted(res.items(), key=lambda x: x[0], reverse=True)
First it find num=3 highest values and create dict with empty list for indexes for it. Next it goes over the list and for every of the highest values (val in res) save it's indexes. Then just return sorted list of tuples like [(highest_1, [indexes ...]), ..]. e.g.
>>> l = [9, 7, 43, 2, 4, 7, 43, 8, 5, 8, 4]
>>> print(search(l))
[(43, [2, 6]), (9, [0]), (8, [7, 9])]
To print the positions do something like:
>>> Fscore_list = [9, 7, 43, 2, 4, 7, 43, 8, 5, 8, 4, 43, 43, 43]
>>> result = search(Fscore_list)
>>> print("1st. %d on positions %s" % (result[0][0], result[0][1]))
1st. 43 on positions [2, 6, 11, 12, 13]
>>> print("2nd. %d on positions %s" % (result[1][0], result[1][1]))
2nd. 9 on positions [0]
>>> print("3rd. %d on positions %s" % (result[2][0], result[2][1]))
3rd. 8 on positions [7, 9]
In one line:
lst = [9,7,43,2,8,4]
index = [i[1] for i in sorted([(x,i) for (i,x) in enumerate(lst)])[-3:]]
print(index)
[2, 0, 1]
None is always considered smaller than any number.
>>> None<4
True
>>> None>4
False
Find the highest element, and its index.
Replace it by None. Find the new highest element, and its index. This would be the second highest in the original list. Replace it by None. Find the new highest element, which is actually the third one.
Optional: restore the found elements to the list.
This is O(number of highest elements * list size), so it scales poorly if your "three" grows, but right now it's O(3n).

return the unique numbers in that list

Can you help me with this homework please?
You are required to complete the function unique_list(l). where "l" is a list of numbers. the function is expected to return the unique numbers in that list.
Example:
(input : [1,1,1,2,2,3,3,3enter code here,4,5,5,6])
output: [1,2,3,4,5,6]
you are not allowed to change the variable names or their values or edit any other code, except the function's body, doing so may jeopardize your evaluation
//no_list = [22,22,2,1,11,11,2,2,3,3,3,4,5,5,5,55,55,66]
//def unique_list(l): //code should be here
//print(unique_list(no_list))
This code pick out the unique elements without changing the order:
no_list = [22,22,2,1,11,11,2,2,3,3,3,4,5,5,5,55,55,66]
def unique_list(l): //code should be here
return list({}.fromkeys(l).keys())
print(unique_list(no_list)) # [22, 2, 1, 11, 3, 4, 5, 55, 66]
Following code will give the unique numbers in a list without changing the order.
>> def unique_list(l):
... final_list = []
... for num in l:
... if num not in final_list:
... final_list.append(num)
... return final_list
...
>>> print (unique_list(no_list))
[22, 2, 1, 11, 3, 4, 5, 55, 66]
Look up the set function and put it back into a list.
You can use a set operation.
no_list = [22,22,2,1,11,11,2,2,3,3,3,4,5,5,5,55,55,66]
set(no_list)
[22,2,1,11,3,4,5,55,66]
You are required to complete the function average(x). where "x" is a list of numbers, and contains more than 3 numbers. the function is expected to return the average from that list.
You can change the numbers in the list no_list but you are not allowed to change the variable names or edit any other code, except the function's body, doing so may jeopardize your evaluation
no_list = [22,68,90,78,90,88]
def average(x):
#complete the function's body to return the average
print(average(no_list))

Moving odd numbers to the end of a list in Python, strange outcome [duplicate]

This question already has answers here:
Strange result when removing item from a list while iterating over it
(8 answers)
Closed 7 years ago.
I'm trying to move the odd numbers in this list to the end without using an external list. When I run the code, it moves half of the odd numbers over, and leaves the other half where they were. The overall output is correct if I run the code twice on the list, but I should only have to run it once, right? What am I doing wrong?
a = [3, 4, 55, 13, 6, 19, 33, 10, 11, 45]
for ind, val in enumerate(a):
if val % 2 != 0:
a.pop(ind)
a.append(val)
print a
Thanks.
This is because, as a general rule, you shouldn't iterate through and modify the same list at the same time. The indices get thrown off!
As you go through and modify the list, not all of the elements actually get cycled through. The a that you are popping is a different list with different indicies after your first change to the list, but you are still using the enumeration of the original version for your loop.
You could use pythons sorting methods (sorted() or someList.sort()) and pass a special key function to it:
>>> sorted(a, key = lambda element: element%2 != 0)
[4, 6, 10, 3, 55, 13, 19, 33, 11, 45]
This is possible because Python sorts are guaranteed to be stable und therefore when multiple records have the same key, their original order is preserved.
Your approach has two problems,
you modify the list on which you iterate
you don't test if the number that slides into the position occupied by an odd number is odd itself
To obviate with 1., you simply can iterate on the indices of your list but to obviate 2., you must start from the end of the list and going towards the beginning, using negative indices.
Executing the following code
a = [3, 4, 55, 13, 6, 19, 33, 10, 11, 45]
for i in range(len(a)):
j = -1-i
if a[j]%2:
a.append(a[j]) ; a.pop(j-1) # j-1 because our list is temporarily longer...
print a
gives you the following output
[4, 6, 10, 45, 11, 33, 19, 13, 55, 3]

Python: Partial sum of numbers [duplicate]

This question already has answers here:
How to find the cumulative sum of numbers in a list?
(25 answers)
Closed 8 years ago.
can you help me with code which returns partial sum of numbers in text file?
I must import text file, then make a code for partial sums without tools ..etc.
My input:
4
13
23
21
11
The output should be (without brackets or commas):
4
17
40
61
72
I was trying to make code in python, but could only do total sum and not partial one.
If i use the += operator for generator, it gives me an error!
Well, since everyone seems to be giving their favourite idiom for solving the problem, how about itertools.accumulate in Python 3:
>>> import itertools
>>> nums = [4, 13, 23, 21, 11]
>>> list(itertools.accumulate(nums))
[4, 17, 40, 61, 72]
There are a number of ways to create your sequence of partial sums. I think the most elegant is to use a generator.
def partial_sums(iterable):
total = 0
for i in iterable:
total += i
yield total
You can run it like this:
nums = [4, 13, 23, 21, 11]
sums = list(partial_sums(nums)) # [ 4, 17, 40, 61, 72]
Edit To read the data values from your file, you can use another generator, and chain them together. Here's how I'd do it:
with open("filename.in") as f_in:
# Sums generator that "feeds" from a generator expression that reads the file
sums = partial_sums(int(line) for line in f_in)
# Do output:
for value in sums:
print(value)
# If you need to write to a file, comment the loop above and uncomment this:
# with open("filename.out", "w") as f_out:
# f_out.writelines("%d\n" % value for value in sums)
numpy.cumsum will do what you want.
If you're not using numpy, you can write your own.
def cumsum(i):
s = 0
for elt in i:
s += elt
yield s
try this:
import numpy as np
input = [ 4, 13, 23, 21, 11 ]
output = []
output.append(input[0])
for i in np.arange(1,len(input)):
output.append(input[i] + input[i-1])
print output
Use cumulative sum in numpy:
import numpy as np
input = np.array([4, 13, 23, 21 ,11])
output = input.cumsum()
Result:
print output
>>>array([ 4, 17, 40, 61, 72])
Or if you need a list, you may convert output to list:
output = list(output)
print output
>>>[4, 17, 40, 61, 72]
This is an alternative solution using reduce:
nums = [4, 13, 23, 21, 11]
partial_sum = lambda a, b: a + [a[-1] + b]
sums = reduce(partial_sum, nums[1:], nums[0:1])
Pluses in lambda are not the same operator, the first one is list concatenation and the second one is sum of two integers. Altough Blckknght's may be more clear, this one is shorter and works in Python 2.7.
something like this:
>>> lst = [4, 13, 23, 21 ,11]
>>> [sum(lst[:i+1]) for i, x in enumerate(lst)]
[4, 17, 40, 61, 72]

Categories