SO i wand to use max() in order to check 3 tuple in the form of (int, str, str),
i want to get the max value of cell 1 out of the 3, but i want to add different ints.
exmpale:
tup_1 = 5, 'adasd', 'dadas'
tup_2 = 4, 'adasda', 'dadad'
tup_3 = 3, 'adasds', 'asdasda'
gap = -2
score = 2
max(tup_1[0] + score, tup_2[0] + gap, tup_3[0] + gap)
i want to get back the tuple with the max value of the first cell, again i wan the tuple not the int, any ideas?
tup_1 = 5, 'adasd', 'dadas'
tup_2 = 4, 'adasda', 'dadad'
tup_3 = 3, 'adasds', 'asdasda'
gap = -2
score = 2
print(max((tup_1[0] + score, tup_1),
(tup_2[0] + gap, tup_2),
(tup_3[0] + gap, tup_3))[1])
Related
I have a data frame, and I want to assign a quartile number based on the quartile variable, which gives me the ranges that I later use in the for. The problem is that instead of just changing the quartile number, it its creating n (len of the datframe) rows, and then using the row number for the loop.
expected result
actual output
quartile = numpy.quantile(pivot['AHT'], [0.25,0.5,0.75])
pivot['Quartile'] = 0
for i in range(0,len(pivot)-1):
if i <= quartile[0]:
pivot.loc[i,'Quartile'] = 1
elif i <= quartile[1]:
pivot.loc[i,'Quartile'] = 2
elif i <= quartile[2]:
pivot.loc[i,'Quartile'] = 3
else:
pivot.loc[i,'Quartile'] = 4
Use qcut with labels=False and add 1 or specify values of labels in list:
pivot['Quartile'] = pd.qcut(pivot['AHT'], 4, labels=False) + 1
pivot['Quartile'] = pd.qcut(pivot['AHT'], 4, labels=[1,2,3,4])
I am trying to write a function that returns from and to bits in [from:to] format.
I am not quite sure how exactly it can be done (recursively?). The expected output is in incremental range of bits. Here is the piece of code to start with,
cntlist = [5,1,4,3,1]
def find_size(cnt):
if cnt>1:
a = "[%s:%s]" % (cnt-1, cnt-cnt)
left = cnt-1
right = cnt-cnt
if cnt==1:
a = "[%s]" % (cnt)
left = a
right = a
return a, left, right
newlist = list(map(find_size, cntlist))
print(newlist)
Output:
[('[4:0]', 4, 0), ('[1]', '[1]', '[1]'), ('[3:0]', 3, 0), ('[2:0]', 2, 0), ('[1]', '[1]', '[1]')]
Expected output:
['[4:0]', '[5]', '[9:6]', '[12:10]', '[13]']
Note: If size is 1 in cntlist, the range will have only one element which will be +1 to previous range's left number.
IIUC, a simple loop should work:
def bitrange(cntlst):
out = []
total = 0
for i in cntlst:
prev = total
total += i
if i == 1:
out.append(f'[{total-1}]')
else:
out.append(f'[{total-1}:{prev}]')
return out
bitrange([5,1,4,3,1])
output:
['[4:0]', '[5]', '[9:6]', '[12:10]', '[13]']
I have, for example, two lists of numbers:
List_numbers_1 = [3, 54, -30]
List_numbers_2 = [65, 8, 800]
I want to create a function that runs the following table of sums:
3 + 65 = 68
54 + 8 = 62
-30 + 800 = 770
The table is lined up, and that is my goal. In order to creat that function I have create other 3 functions that maybe will help me:
'''it returns the width of a number '''
def max_width(List_numbers_1):
string_List_numbers_1 = map(str, List_numbers_1)
width_List_numbers_1 = map(len, string_List_numbers_1)
return max(width_List_numbers_1)
Output: 3
'''it returns the padd for a number'''
def left_padded(number, width):
return str(number).rjust(width)
left_padded(54, 5)
' 54'
left_padded(-56, 5)
' -56'
'''It returns a padd for all the numbers of the list'''
def all_left_padded(List_numbers_1, width):
return list(map(lambda number: left_padded(number, width), List_numbers_1))
all_left_padded(List_numbers_1, 5)
[' 3', ' 54', ' -30']
I think the above functions can be useful for my last function. Nevertheless, I will really appreciate any other idea. If it is possible I would prefer a function that use the return statement but with print() will be ok.
I fact I think this function has to contain return and print as well.
THANK YOU
Without numpy, you can zip the lists together and add them up:
[sum(i) for i in zip(lst1,lst2)]
It is easier to use a list comprehension rather than map
For formatting the numbers it is natural to use str.format().
As you don't know the widths of the numbers in advance, you first create
a format string, and the easiest way to do that is to use format
# maxlen returns the length of the longest element
def maxlen(l):
return max([len(str(i)) for i in l])
# sumtable returns a formatted multiline string containing the sums
# written in a human readable form.
def sumtable(l1,l2):
#sums contains the answers, and table is the full table numbers in
#the calculations as a list of tuples
sums = [sum(i) for i in zip(l1,l2)]
table = list(zip(l1,l2,sums))
width1 = maxlen(l1)
width2 = maxlen(l2)
widthsum = maxlen(sums)
# formatstring has a form like "{:3d} + {:5d} = {:5d}\n"
formatstring = "{{:{}d}} + {{:{}d}} = {{:{}d}}\n".format(width1,width2,widthsum)
# unpack the values from the table into the format string and return.
return (formatstring.format(*table[0])
+ formatstring.format(*table[1])
+ formatstring.format(*table[2]))
print(sumtable([3,54,-30],[65,8,800]))
# 3 + 65 = 68
# 54 + 8 = 62
# -30 + 800 = 770
If you can use a 3rd party library, this is trivial with numpy:
import numpy as np
lst1 = [3, 54, -30]
lst2 = [65, 8, 800]
res = np.sum([lst1, lst2], axis=0)
# array([ 68, 62, 770])
`in order to display the table of sums'''
>def table(L1, L2):
Sum = list(map(lambda x, y: x + y, L1, L2))
widthL1 = max_width(L1)
widthL2 = max_width(L2)
widthSum = max_width(Sum)
first_column = all_left_padded(L1, widthL1)
second_column = all_left_padded(L2, widthL2)
third_column = all_left_padded(Sum, widthsum)
triplets = zip(first_column, second_column, third_column)
return list(map(lambda triplet: str_sum(triplet), triplets))
# for displaying the table
>def printable(L1, L2):
t = table(L1, L2)
for row in t:
print(row)
😀
# the str_sum function was:
def str_sum(Tuple):
return '{ } + { } = { }'.format(Tuple)
> str_sum((2,3,5))
'2 + 3 = 5'
# I was thinking: why instead summing two Lists, I will sum n lists?
# I would create two functions
>L1 = [1, 2]
>L2 = [2, 3]
> L3 = [4, 5]
> Group = (L1, L2, L3)
> Sum = [sum(l) for l in zip(*Group)]
>Sum
[7, 10]
# and for creating a Tuple with n elements because if the table has n Lists the Tuple must have n elements
> def str_sum(Tuple):
n = len (Tuple)
f = ((n -2)*'{ } + ' + '{ } = { }')
return f.format(*Tuple)
>str_sum((1, 2, 3, 8, 7, 21))
('1 + 2 + 3 + 8 + 7 = 21')
ratings_dict is a dictionary with the format: {'userName' : [0, 0, 1, 0, etc]}
I'm attempting to access each element in the list (in the dictionary) and it is giving me a specific error at 'if ratings_dict[name][i] is not 0:' and it is saying that IndexError: list index out of range.
Edited: This is my revised code. As you can see from the traceback, the value at ratings_dict['Martin'][0] is 1.
I have also revised my code in mind of your efficiency tips..
I am still at a loss at what to do.
def calculate_average_rating(ratings_dict):
ratings = {}
numBooks = len(ratings_dict)
print ratings_dict['Martin'][0]
for i in range(numBooks):
x = 0
sum = 0
numR = 0
for name in ratings_dict:
if ratings_dict[name][x] != 0:
sum = sum + ratings_dict[name][x]
numR += 1
x = x + 1
if numR is 0:
ratings[i] = 0
if sum != 0:
ratings[i] = float(sum) / float(numR)
return ratings
Output:
1
Traceback (most recent call last):
File "C:\Users\Collin\Dropbox\Python Files\main.py", line 106, in <module>
main()
File "C:\Users\Collin\Dropbox\Python Files\main.py", line 103, in main
print calculate_average_rating(ratingsDict)
File "C:\Users\Collin\Dropbox\Python Files\main.py", line 10, in calculate_average_rating
if ratings_dict[name][x] != 0:
IndexError: list index out of range
If you're getting an index error but don't "believe" that you should be, just print out the list and you will see the problem.
a = [0]
Imagine you didn't know what a was and then ran this code:
for i in range(2):
try :
x = a[i]
except IndexError:
print('IndexError, list = ' + str(a) + ', index = ' + str(i))
Then you would see
IndexError, list = [0], index = 1
and so the problem is clear. If the list is too long to print nicely, you can simply print the length instead of the list.
As others have already pointed out, it is very hard to say what is causing the IndexError without looking at ratings_dict. Most likely, the error is happening because the list containing the ratings has different length for different users. You are calculating the length using len(ratings_dict[Names[0]]), which is the length of the list corresponding to the first (i.e. 0th user). If the second user's list has a shorter length, then you will get an IndexError.
In more detail, here's what I mean. Suppose your ratings_dict is as follows:
ratings_dict = {"martin" : [1, 4, 3, 4, 5],
"tom" : [0, 1, 2, 1, 5],
"christina" : [0, 0, 2, 2, 3],
}
and we use the following function (I basically simplified your function a little bit)
def calculate_average_rating(ratings_dict):
names = [key for key in ratings_dict]
numBooks = len(ratings_dict[names[0]])
ratings = []
for i in range(numBooks):
total = 0
for name in names:
if ratings_dict[name][i] != 0:
total = total + ratings_dict[name][i]
ratings.append(float(total) / len(names))
return ratings
then we get no IndexError.
calculate_average_rating(ratings_dict)
[0.3333333333333333,
1.6666666666666667,
2.3333333333333335,
2.3333333333333335,
4.333333333333333]
However, if we Christina has reviewed an additional book and ratings_dict looks as follows:
ratings_dict = {"martin" : [1, 4, 3, 4, 5],
"tom" : [0, 1, 2, 1, 5],
"christina" : [0, 0, 2, 2, 3, 6],
}
then running the function gives an IndexError:
calculate_average_rating(ratings_dict)
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-23-1ad9c374e8d8> in <module>()
----> 1 calculate_average_rating(ratings_dict)
<ipython-input-14-080a1623f225> in calculate_average_rating(ratings_dict)
6 total = 0
7 for name in names:
----> 8 if ratings_dict[name][i] != 0:
9 total = total + ratings_dict[name][i]
10
IndexError: list index out of range
It happens because the lists of different users do not have equal length.
Slightly off topic, it is not considered good practice to use capital letters to start variable names, because it can be confused for being a Class. See PEP8 for more details. Therefore, consider changing Names to names.
Secondly, you shouldn't use is not for doing comparisons. In this particular case, it won't bite you. But in some cases, it will. For example:
>>> a = 1000
>>> b = 1000
>>> a is b
False
The is operator compares whether a and b are the same objects, and not their values. In this case, a and b are different objects with the same value, therefore a is b evaluates to False.
I have got a problem with my code. I'm trying to use the variable channels_index under the loop to get each element from the list once at a time without keep looping but I have got an error: TypeError: can't multiply sequence by non-int of type 'float'
When I try this:
dbconnect = con.cursor()
dbconnect.execute("SELECT COUNT(*) FROM programs")
x = dbconnect.fetchone()[0]
for channels_range, total_channels in enumerate(xrange(1, x + 1, 69), 1):
pass
channels_index = range(0, channels_range) # count how many channels I have got
for ind, row in enumerate(programs):
program = row[1].encode('ascii'), str(row[2]), str(row[3])
title = row[1].encode('ascii')
program_start_date = str(row[2])
program_end_date = str(row[3])
program_height = 33
program_gap = 3
position_top = programs_top + channels_index * (program_height + program_gap + 1.5)
The error are highlight on this line:
position_top = programs_top + channels_index * (program_height + program_gap + 1.5)
Here is a list of elements:
18:22:32 T:3680 NOTICE: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
I'm connecting to a database to fetch the data from every 69 rows to counts on how many rows I have got in a range. I can't put the value of 17 in the line for that code position_top = programs_top + value, because I won't know how many 69 rows I have got in a database.
Can you please help me how I can use the variable channels_index under the loop to fetch each element from a list once at a time without keep looping?
If you wanted to cycle through the values 0 through channels_range, then use a modulus:
channels_index = 0
for ...:
channels_index = (channels_index + 1) % channels_range
This will increment channels_index to 1, then 2, all the way up to channels_range - 1, then go back to 0.
There is no need to produce a list of values up front here.
If you wanted to calculate 69 times 0, then 69 times 1, etc. counting up to 16, you can still calculate that simply from the row index:
for ind, row in enumerate(programs):
channel_index = ind // 69
The row indices 0 through to 68, divided by 69 produce 0. Indices 69 through to 137 give 1, etc.
I'm not sure I get exactly what you're asking, but if you're trying to grab indices from channels_index one at a time, why not just add it to your for loop?
# same as above...
for (ind, row), ch_idx in zip(enumerate(programs), channels_index):
# continue on as before
position_top = programs_top + ch_idx * (program_height + program_gap + 1.5)