I am new to python so a simplified explanation would be much appreciated!
As of now I have a dictionary that looks like this:
names = {'Bob Smith': ['5', '6', '7', '5'], 'Fred Jones': ['8', '5', '7', '5', '9'], 'James Jackson': ['5','8','8','6','5']}
I need to do the following:
Take the last three items from each of the entries in the dict. e.g. 6, 7, 5 for bob smith.
Calculate an average based upon those values. e.g. Bob smith would be 6.
List the averages in order from highest to lowest (without the dict keys).
So far I have the following enclosed in an if statement:
if method == 2:
for scores in names.items():
score = scores[-1,-2,-3]
average = sum(int(score)) / float(3)
print(average)
I had a look at this thread too but I am still stuck.
Can anyone give me some pointers?
Scores[-1,-2,-3] does not get the last three elements. It gets the element at the key (-1,-2,-3) in a dictionary, which will raise an error in the case of a list. Scores[-3:] would get the last three elements.
When getting the scores, you need to use names.values() instead of names.items()
The python string-to-integer conversions in the int type constructor are not smart enough to handle lists of strings, only individual strings. Using map(int,score) or int(i) for i in score would fix that.
The variable score is also an extremely poor choice of name for a list of elements.
In Python3.4+, there is a statistics module
>>> names = {'Bob Smith': ['5', '6', '7', '5'], 'Fred Jones': ['8', '5', '7', '5', '9'], 'James Jackson': ['5','8','8','6','5']}
>>> import statistics
>>> sorted((statistics.mean(map(int, x[-3:])) for x in names.values()), reverse=True)
[7.0, 6.333333333333333, 6.0]
names = {'Bob Smith': ['5', '6', '7', '5'], 'Fred Jones': ['8', '5', '7', '5', '9'], 'James Jackson': ['5','8','8','6','5']}
def avg(l):
l = list(map(int,l))
return sum(l[-3:])/3
avgs = []
for each in names.values():
avgs.append(avg(each))
avgs.sort(reverse=True)
print avgs
Output:
[7, 6, 6]
Related
I have a list. I am using Counter as below.
Here, I need to agregate the counting of movie names according to years.
listt = [['1', '1995'],
['2', '1993'],
['3', '1992'],
['4', '1993'],
['5', '1995'],
['6', '1995'],
['7', '1996'],
['8', '1993'],
['9', '1992'],
['10', '1992'],
['11', '1995'],
['12', '1994'],
['13', '1995']]
c=Counter(listt[0:][3])
Edited:
In this listt, I count movies names (like 'Toy Story','Jumanji') according to years (like'1995')
Expected result:
enter image description here
You could simply use a comprehension list to reduce each entry to just its year (as you really don't care about neither the name nor the genre), and then using that as input for the Counter.
Finally, you can take advantage of the most_common method:
https://stackoverflow.com/a/27303678/5745962
https://docs.python.org/3/library/collections.html#collections.Counter
movies_years = [x[3] for x in listt]
c = Counter(movies_years)
print(c.most_common(5))
# Output: [('1995', 5), ('1993', 3), ('1992', 3), ('1996', 1), ('1994', 1)]
I have a list of lists:
data = [['2001', '20', '0', '0', '10', '0', '15', '0'],
['2004', '15', '0', '9.5', '13', '10', '18', '30']]
My work is to use items of sublists in this list of lists:
def FinalMark(studentNum):
if studentNum in data:
I don't know what to do next. Let's say if 2001 is the first item of a sublist, I want to know how to use others items of this sublist.
There are better ways to do it by storing the data as a dictionary. But with what you have, you can loop through data:
def FinalMark(studentNum):
for marks in data:
if marks[0] == studentNum:
return sum([float(i) for i in marks[1:]])
marks[1:] is a slice of marks that skips the first element (the student number).
The problem at hand is I have a list of lists that I need to iterate through and compare one by one.
def stockcheck():
stock = open("Stock.csv", "r")
reader = csv.reader(stock)
stockList = []
for row in reader:
stockList.append(row)
The output from print(stockList) is:
[['Product', 'Current Stock', 'Reorder Level', 'Target Stock'], ['plain blankets', '5', '10', '50'], ['mugs', '15', '20', '120'], ['100m rope', '60', '15', '70'], ['burner', '90', '20', '100'], ['matches', '52', '10', '60'], ['bucket', '85', '15', '100'], ['spade', '60', '10', '65'], ['wood', '100', '10', '200'], ['sleeping bag', '50', '10', '60'], ['chair', '30', '10', '60']]
I've searched the basics for this but i've had no luck... I'm sure the solution is simple but it's escaping me! Essentially I need to check whether the current stock is less than the re-order level, and if it is save it to a CSV (that part I can do no problem).
for item in stockList:
if stockList[1][1] < stockList[1][2]:
print("do the add to CSV jiggle")
This is as much as I can do but it doesn't iterate through... Any ideas? Thanks in advance!
Iterate through the stockList using list comprehension, maybe and then print out the results
[sl for sl in stockList[1:] if sl[1] < sl[2]]
You will get the following results:
[['mugs', '15', '20', '120']]
In case you were wondering stockList[1:] is to ensure that you ignore the header.
However, you must note that the values are strings that are being compared. Hence, the values are compared char by char. If you want integer comparisons then you must convert the strings to integers, assuming you are absolutely sure that sl[1] and sl[2] will always be integers - just being presented as strings. Just try doing:
[sl for sl in stockList[1:] if int(sl[1]) < int(sl[2])]
The result changes:
[['plain blankets', '5', '10', '50'], ['mugs', '15', '20', '120']]
Use the [1:] to not get the header, and then make the comparation.
for item in stockList[1:]:
if item[1] < item[2]:
print item
print("do the add to CSV jiggle")
I have a controlled assessment, and need to be able to order scores from a test in numerical and alphabetical order. How do i do this if they are connected to the persons name who completed the quiz. All names are within 1 list, For example ["John, 9"], ["alfie, 6"] etc
any help much appreciated!
If you want to sort a list of strings based on a transformation on each of these strings, you can use the function sorted with the key keyword argument:
>>> l = ['10', '9', '100', '8']
>>> sorted(l)
['10', '100', '8', '9']
>>> sorted(l, key=int)
['8', '9', '10', '100']
>>> def transformation(x):
... return -int(x)
...
>>> sorted(l, key=transformation)
['100', '10', '9', '8']
What the key function does is that the strings are not compared directly, but the values that are returned by the function are.
Starting with two lists such as:
lstOne = [ '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
lstTwo = [ '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
I want to have the user input how many items they want to extract, as a percentage of the overall list length, and the same indices from each list to be randomly extracted. For example say I wanted 50% the output would be
newLstOne = ['8', '1', '3', '7', '5']
newLstTwo = ['8', '1', '3', '7', '5']
I have achieved this using the following code:
from random import randrange
lstOne = [ '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
lstTwo = [ '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
LengthOfList = len(lstOne)
print LengthOfList
PercentageToUse = input("What Percentage Of Reads Do you want to extract? ")
RangeOfListIndices = []
HowManyIndicesToMake = (float(PercentageToUse)/100)*float(LengthOfList)
print HowManyIndicesToMake
for x in lstOne:
if len(RangeOfListIndices)==int(HowManyIndicesToMake):
break
else:
random_index = randrange(0,LengthOfList)
RangeOfListIndices.append(random_index)
print RangeOfListIndices
newlstOne = []
newlstTwo = []
for x in RangeOfListIndices:
newlstOne.append(lstOne[int(x)])
for x in RangeOfListIndices:
newlstTwo.append(lstTwo[int(x)])
print newlstOne
print newlstTwo
But I was wondering if there was a more efficient way of doing this, in my actual use case this is subsampling from 145,000 items. Furthermore, is randrange sufficiently free of bias at this scale?
Thank you
Q. I want to have the user input how many items they want to extract, as a percentage of the overall list length, and the same indices from each list to be randomly extracted.
A. The most straight-forward approach directly matches your specification:
percentage = float(raw_input('What percentage? '))
k = len(data) * percentage // 100
indicies = random.sample(xrange(len(data)), k)
new_list1 = [list1[i] for i in indicies]
new_list2 = [list2[i] for i in indicies]
Q. in my actual use case this is subsampling from 145,000 items. Furthermore, is randrange sufficiently free of bias at this scale?
A. In Python 2 and Python 3, the random.randrange() function completely eliminates bias (it uses the internal _randbelow() method that makes multiple random choices until a bias-free result is found).
In Python 2, the random.sample() function is slightly biased but only in the round-off in the last of 53 bits. In Python 3, the random.sample() function uses the internal _randbelow() method and is bias-free.
Just zip your two lists together, use random.sample to do your sampling, then zip again to transpose back into two lists.
import random
_zips = random.sample(zip(lstOne,lstTwo), 5)
new_list_1, new_list_2 = zip(*_zips)
demo:
list_1 = range(1,11)
list_2 = list('abcdefghij')
_zips = random.sample(zip(list_1, list_2), 5)
new_list_1, new_list_2 = zip(*_zips)
new_list_1
Out[33]: (3, 1, 9, 8, 10)
new_list_2
Out[34]: ('c', 'a', 'i', 'h', 'j')
The way you are doing it looks mostly okay to me.
If you want to avoid sampling the same object several times, you could proceed as follows:
a = len(lstOne)
choose_from = range(a) #<--- creates a list of ints of size len(lstOne)
random.shuffle(choose_from)
for i in choose_from[:a]: # selects the desired number of items from both original list
newlstOne.append(lstOne[i]) # at the same random locations & appends to two newlists in
newlstTwo.append(lstTwo[i]) # sequence