Calculating averages - python

I've struggled with calculating average for values in 2 different lists. Here is what I have been doing (as newbie in python):
Averagelist = []
Listofvalues1 = ['1', '2', '3', '4']
Listofvalues2 = ['5', '6', '7', '8']
for i, x in enumerate(Listofvalues1):
for j, y in enumerate(Listofvalues2):
if j == i:
AVGvalue = (int(x)+int(y)/2)
Averagelist.append(AVGvalue)
I've come up with this way by myself. It might be useless, but so far I can print both values that I want to use for calculation but I get an error "ValueError: invalid literal for int() with base 10: 'somevalue'". Could it be the '' sign?
Cheers!

Do you need your data to be stored as strings? You will have to covert them to numbers (floats) at one time. This can be done without a for loop, using list comprehension:
Listofvalues1 = ['1', '2', '3', '4']
Listofvalues2 = ['5', '6', '7', '8']
Averagelist = [(float(v1)+float(v2))/2 for (v1, v2) in zip(Listofvalues1, Listofvalues2)]

To calculate the actual average without having it rounded down, use float. Also you needed an extra pair of brackets otherwise it would be y/2 rather than (x+y/2).
As for that error, I'm not sure what you're using in your Listofvalues lists as input, the the following worked fine for me.
Averagelist = []
Listofvalues1 = [1,2]
Listofvalues2 = [6,7]
for i, x in enumerate(Listofvalues1):
for j, y in enumerate(Listofvalues2):
if j == i:
AVGvalue = ((float(x)+float(y))/2)
Averagelist.append(AVGvalue)
print Averagelist

Did you mean (int(x)+int(y))/2 instead of (int(x)+int(y)/2)?

You can try:
averages = [(float(e[0]) + float(e[1]))/2 for e in zip(Listofvalues1, Listofvalues2)]

Related

Checking if values from different lists are less than x

I can't use csv module so I'm opening a csv file like this:
def readdata(filename):
res = []
tmp = []
with open(filename) as f:
l = f.readlines()
for i in range(len(l)):
tmp.append(l[i].strip().split(';'))
for i in range(len(tmp)):
for j in range(len(tmp[i])):
if j > len(res)-1:
res.append([])
res[j].append(tmp[i][j])
return res
res_count_file = "count.csv"
data_count_file = readdata(res_count_file)
This csv file contain this:
ro1;ro2;ro3
5;3;5
8;2;4
6;2;666
15;6;3
2;1;
6;9;7
Now my function read this and splits them into a list of 3 lists :
[['ro1', '5', '8', '6', '15', '2', '6'], ['ro2', '3', '2', '2', '6', '1', '9'], ['ro3', '5', '4', '666', '3', '', '7']]
I need to check if the values of a row are each less then x(let's say x = 10), and if they're not then :score+= 1
For exemple:
5;3;5 //none of them are greater then x so score += 1
8;2;4 //none of them are greater then x so score += 1
15;6;3 // 15 is greater then x so nothing happens
2;1; // none of them are greater then x so score += 1 even if there is nothing in ro3, I need to convert the empty string "''" into 0
Now I've tried to call this function in a for loop to check if a number is less then X and to increment score if this returns true but I can't figure out how to check all 3 of the numbers in R01 R02 R03 as shown in the exemple.
def apprenant_fiable(data,index_of,i):
if data[index_of][i] == "":
return True
elif int(data[index_of][i]) <= 10 :
#print(data[index_of][i],"***PASS")
return True
else :
#print(data[index_of][i],"***FAIL")
return False
The goal is to output the total score.
You can use sum on a generator:
lst = [['ro1', '5', '8', '6', '15', '2', '6'], ['ro2', '3', '2', '2', '6', '1', '9'], ['ro3', '5', '4', '666', '3', '0', '7']]
val = 10
score = sum(all(y <= val for y in x) for x in zip(*[map(int, x[1:]) for x in lst]))
# 4
Note that I've replaced empty string in the list to '0', which you need to handle while forming the list.
val = 10
for x in zip(*[map(int, x[1:]) for x in lst]):
if all(y <= val for y in x):
print(x)
This will now print out all rows that contributed to adding score.
Your problem is in the head of your function:
def apprenant_fiable(data, index_of, i):
########
You specifically tell your function to look at only one of the three lists. Get rid of this. Inside the function you will somewhere have
for value, index in enumerate(data)
You will need to check all the values before deciding what to return.
If you can't figure out how to do this, there are many places to teach you how to look for presence of a certain quality in a collection.
you can do it easly using the pandas module
import pandas as pd
# read the csv
df = pd.read_csv('input.csv', delimiter=';').fillna(0)
# leave only the rows with sum greater then 10
print(df[df.sum(axis=1) > 10].shape[0])
Something like this? where list_of_3_lists is your result of reading the input file
total = 0
for l in list_of_3_lists:
if all([int(t) > 10 for t in l[1:]]):
total +=1
print(total)

How to save an element from a list as a whole after an if-statement

I want to save elements of a list as a whole in a new list.
My new task is to transform nested lists into a flat one. My plan was to take out the elements of each list and save them into a variable. And in the end to put the variables together, so that there is just a flat list at the end.
I have two problems:
The index-3 element ('99999') isn't saved as a whole in the list of the new variable. This problem is the topic of this question.
I cannot separate the nested list [66, 77, 88] from the higher list ['4', '5',[]], but this is not the topic of this question
So here is the code of the nested list and of my if statement:
nested_list = ['1', '2', '3', '99999',['4', '5',[66, 77, 88]]]
y = []
for i in nested_list:
if type(i) != (list or tuple):
y += i
print(y)
I want the index=3 element (the string '99999') be saved in the variable y as a whole string and not split into the single parts '9', '9', '9', '9', '9'
I want:
print(y)
['1', '2', '3', '99999']
I get:
print(y)
['1', '2', '3', '9', '9', '9', '9', '9']
I can't solve the problem with saving into a string (y = ' '), because than I get the result:
print(y)
12399999
and if I would transform the string to a list
y = list(y)
I get the same unwanted result
['1', '2', '3', '9', '9', '9', '9', '9']
I think the solution lies in the action code after the if-statement
y += i
Is there a command, which takes the whole element into y? I tried y += sum(i) but of course this didn't work, because
it adds up all numbers like int, floats, etc.., not strings
I don't need to add 9+9+9+9+9=45, but I need just the whole string in my new list y.
I don't know if i understand you right:
# List comprehension:
y = [x for x in nested_list if not isinstance(x, (list, tuple))]
# gives: ['1', '2', '3', '99999']
It would be the same as:
nested_list = ['1', '2', '3', '99999',['4', '5',[66, 77, 88]]]
y = []
for i in nested_list:
if not isinstance(i, (list or tuple)):
y.append(i) # This maybe your failure
print(y)
Does this help you or do you need to have all other elements also in your output list?
(i only recognized your example)
Additional if you want to iterate over all and flatten the whole list:
nested_list = ['1', '2', '3', '99999',['4', '5',[66, 77, 88]]]
y = []
def flatten_list(lst):
if isinstance(lst, (list, tuple)):
if len(lst) == 0:
return []
first, rest = lst[0], lst[1:]
return flatten_list(first) + flatten_list(rest)
else:
return [lst]
y = flatten_list(nested_list)
print(y) # ['1', '2', '3', '99999', '4', '5', 66, 77, 88]
One issue is that (list or tuple) evaluates to a boolean itself, and rather you should use isinstance for type checking
Then, try appending to the list rather than adding stings, which are iterable in themselves. For example, you could've tested [] + '9999' independently for your problem
y = []
for i in nested_list:
if isinstance(i, (list, tuple));
y.append(i)

Generated List consists of [Apparantly] unaccounted whitespaces in this code snippet

For a routine question on python programming, I was asked to generate a list of string sliced from one string (let's call it as target_string), with the length of each sliced string increasing from 1 to the length of string.
For example, if target_string is '123', I would have to generate the list like this : ['1', '2', '3', '12', '23', '123'].
For this, I wrote a code snippet that was something like this:
target_string = raw_input("Target String:")
length = len(target_string)
number_list = []
for i in range(length):
for j in range(length):
if j + i <= length:
number_list.append(target_string[j:j + i])
print(number_list)
On execution of this the result was:
Target String:12345
['', '', '', '', '', '1', '2', '3', '4', '5', '12', '23', '34', '45', '123', '234', '345', '1234', '2345']
The first thing I noticed is that the list consists of whitespaces as elements, and the number of whitespaces is equal to the length of the target_string. Why does this happen? Any kind of clarification and help is welcome.
P.S: I have a temperory workaround to generate the list that I need:
target_string = raw_input("Target String:")
length = len(target_string)
number_list = []
for i in range(length):
for j in range(length):
if j + i <= length:
number_list.append(target_string[j:j + i])
number_list.append(target_string)
del number_list[0:length]
target_list = [int(i) for i in number_list]
print(target_list)
Also feel free to suggest any changes or modifications to this, or any approach you would feel is more efficient and pythonic. Thanks in advance.
Edit: This is implemented in Pycharm, on Windows 10 , using Python 2.7, but please feel free to give the solutions in both the Python 2.7 and 3.X versions.
You can use itertools.combinations, then get the ones that the indexes are continuously adding 1, use ''.join(..) for converting it o a string and add it using .extend(..):
Python 2.7:
import itertools
target_string = raw_input("Target String:")
l=[]
for i in range(1,len(target_string)+1):
l.extend([''.join(i) for i in itertools.combinations(target_string,i) if all(int(y)-int(x)==1 for x, y in zip(i, i[1:]))])
print l
Output:
['1', '2', '3', '12', '23', '123']
Python 3.x:
import itertools
target_string = input("Target String:")
l=[]
for i in range(1,len(target_string)+1):
l.extend([''.join(i) for i in itertools.combinations(target_string,i) if all(int(y)-int(x)==1 for x, y in zip(i, i[1:]))])
print(l)
Output:
['1', '2', '3', '12', '23', '123']
Explaining why you got whitespaces in your code snippet.
Have a look at the loop part:
for i in range(length):
for j in range(length):
if j + i <= length:
number_list.append(target_string[j:j + i])
Here, both i and j gets initiated with 0.
So when we decode it, it comes like:
i = 0:
j=0:
0+0 < length
number_list.append(for i in range(length):
for j in range(length):
if j + i <= length:
number_list.append(target_string[0:0 + 0])) --> ['']
and so on.....

Finding the index of the first element of a list in another list

main_list = ['4', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
my_list = ['4', '5', '6']
My question is, how to find index of my_list in main_list?
The integers in my_list must be in consecutive order in main_list.
I tried using main_list.index(my_list[0]) but if there are more than one of a specific element, it returns the wrong index number. The result I need to get is 4, however with main_list.index(my_list[0]) it'll just give 0 as its index.
If there is any need for clarification, I can edit the post with additional details. Sorry, English is not my first language.
Try something like this
for i in range(len(main_list)-len(my_list)):
if main_list[i:i+len(my_list)] == my_list:
index = i
break
This should work for all possible types that could go in the lists.
You can convert both lists into a string using join() function and iteratively compare the strings to find a match.
EDIT: Made a change for it two work for multi-digit numbers. Added a float case as well.
For example:
main_list = ['4', '1', '2', '3', '40.1', '52', '61', '7', '8', '9', '10']
my_list = ['40.1', '52', '61']
index = -1
for i in range(len(main_list)):
if '#'.join(main_list[i:i+len(my_list)]) == '#'.join(my_list):
index = i
break
print(index)
If you would like an algorithm solution:
def Find(haystack, needle):
n, h = len(needle), len(haystack)
assert n <= h
for i in range(h):
if h - i <= n: break
count = 0
for i_, j in zip(range(i, i + n), range(n)):
if haystack[i_] == needle[j]:
count += 1
if count == n: return i
return -1
A much more effective one liner :
print ','.join(main_list).find(','.join(my_list)) - ''.join(main_list).find(''.join(my_list))
Converts them to strings with the elements separated by commas, finds the occurrence, then subtracts the occurrence found when the commas aren't there, and you have your answer.

How to reverse a list of strings without reversed() or [::-1] in Python

I made a post about this recently but didn't go into proper detail and I don't really know how commenting works on this website so I thought I'd create another thread with proper detail (if that's okay, sorry if it isn't)
Simply put, I'm writing code that prompts for and reads a string from a user (eg: 12345). This string could be infinitely long (eg: 123456789123456789, etc). After this string is entered, my code then takes each element from that string and puts it into a list (eg, 12345 is turned into ['1', '2', '3', '4', '5']).
What I need help with is reversing this list of strings without using reversed() or [::-1], and for it to work with a list of strings that could be infinitely long (eg, ['1', '2', '3', '4', '5'] turns into ['5', '4', '3', '2', '1']).
I know this is very basic, but I've spent quite a while trying to think of how to do this and for some reason my slow brain can't grasp a way how to. The best way for me to learn is to see it being done, with an explanation as to how it works (or I could look at the code and figure out the 'how' part by myself). I would be extremely appreciative for help on this, and thankyou in advance!
How about this
x = input('enter the values:')
x = list(x)
res = []
for i in range(len(x) -1, -1, -1):
res.append(x[i])
print(res)
In addition to using reversed() or L[::-1], you could use list.reverse() to reverse the elements of the list in-place:
>>> L = ['1', '2', '3', '4', '5']
>>> L.reverse()
>>> L
['5', '4', '3', '2', '1']
You can implement reversed() yourself with a for loop:
>>> L = ['1', '2', '3', '4', '5']
>>> R = []
>>> for i in range(len(L)-1, -1, -1):
... R.append(L[i])
...
>>> R
['5', '4', '3', '2', '1']
lst1 = [1,2,3,4,5,6]
reversed_list = []
length = len(lst1)
for r in range(0, length ):
reversed_list.append( lst1[length - r - 1] )
print reversed_list
x="hey there"
l=len(x)
out=''
while l:
out=out+x[l-1]
l-=1
print out
This is what you are looking for. Start at end of sting on work backwards and append it to an out var

Categories

Resources