Create list from objects in Python - python

I'm having troubles creating a list from the numbers I made using my code.
ListA = [5,1,3,8,4]
LengthB = (len(ListA))
obj0 = ListA[0]
obj1 = ListA[1]
obj2 = ListA[2]
obj3 = ListA[3]
obj4 = ListA[4]
obj01 = int(obj0)
obj11 = int(obj1)
obj21 = int(obj2)
obj31 = int(obj3)
obj41 = int(obj4)
obj010 = obj01+obj11
obj110 = obj01+obj11+obj21
obj210 = obj11+obj21+obj31
obj310 = obj21+obj31+obj41
obj410 = obj31+obj41
ListBnum0 = (obj010 / 2)
ListBnum1 = obj110 / 3
ListBnum2 = obj210 / 3
ListBnum3 = obj310/ 3
ListBnum4 = obj410 / 2
print(ListBnum0)
print(ListBnum1)
print(ListBnum2)
print(ListBnum3)
print(ListBnum4)
FinalForm1 = str(ListBnum0)
FinalForm2 = str(ListBnum1)
FinalForm3 = str(ListBnum2)
FinalForm4 = str(ListBnum3)
FinalForm5 = str(ListBnum4)
Basically this program takes the ListA numbers and computes the average of the one behind the number, the number and number after if applicable. My real question is how can I take either ListBnum(0) to ListBnum(4) and create another list out of the numbers?
Why does this return an error below?
ListB = list[ListBnum0,ListBnum1,ListBnum2,ListBnum3,ListBnum4]

The direct answer to your question is:
new_list = [ListBnum0, ListBnum1, ListBnum2, ListBnum3, ListBnum4]
The reason you get an error when doing this:
ListB = list[ListBnum0,ListBnum1,ListBnum2,ListBnum3,ListBnum4]
… is that list is a function, and function calls need parentheses to call them. You could write it like this:
ListB = list([ListBnum0,ListBnum1,ListBnum2,ListBnum3,ListBnum4])
However, there's no reason to do so. What the list function does is to take any iterable as an argument, and return a list with the same values. But [ListBnum0, …] is already a list, so you're just making a copy for no reason.
Meanwhile, this whole design is clunky. Better to process the whole list at a time, than to split it into 5 separate variables and process them one by one and merge them back into a list. For example:
ListA = [5,1,3,8,4]
List0 = [int(i) for i in ListA]
def avg(x):
return sum(x) / len(x)
ListB = [avg(List0[max(i-1, 0):i+2]) for i in range(len(List0))]
ListFinal = [str(i) for i in ListB]

Related

I don't know why it's an empty list? max()

# Plot the highest score in history
def draw_best(background):
ip = 'redis-16784.c89.us-east-1-3.ec2.cloud.redislabs.com'
r = redis.Redis(host=ip, password=1206, port=16784, db=0, decode_responses = True)
scores = [eval(i) for i in list(r.hgetall('2048').values())]
best_scores = max(scores)
scoreSurf = BasicFont01.render('Top score:{}'.format(best_scores), True, (0, 0, 0))
scoreRect = scoreSurf.get_rect()
scoreRect.width = math.floor((rate - 0.15) / 2 * screen.get_width())
scoreRect.height = math.floor((1 - rate2) / 3 * 2 * screen.get_height())
scoreRect.topright = (math.floor(0.9 * screen.get_width()), math.floor(0.05 * screen.get_height()))
py.draw.rect(screen, background, [scoreRect.topleft[0], scoreRect.topleft[1], scoreRect.width, scoreRect.height], 0)
screen.blit(scoreSurf, scoreRect)
I think the problem is in these two lines:
scores = [eval(i) for i in list(r.hgetall('2048').values())]
best_scores = max(scores)
The error it showed me was:
ValueError: max() arg is an empty sequence
Obviously, it seems like list(r.hgetall('2048').values()) is a blank sequence/list/array.
Check if it is really empty by defining a variable with the value list(r.hgetall('2048').values()) and then print it out to check.
There is a default keyword that may be helpful. It will return a value if the list is empty. It works as follows:
my_list = []
result = max(my_list, default=None)
print(result) # It will print "None"
You already think that the problem exists in those two lines, then what better way to solve this is to check if it is really in those two lines!

Automatically pass variables names to list

I have a long chain of code for a portion of a script. For example:
B1_2013 = images.select('0_B1')
B2_2013 = images.select('0_B2')
B3_2013 = images.select('0_B3')
B4_2013 = images.select('0_B4')
B5_2013 = images.select('0_B5')
B6_2013 = images.select('0_B6')
B7_2013 = images.select('0_B7')
B8_2013 = images.select('0_B8')
B9_2013 = images.select('0_B9')
B10_2013 = images.select('0_B10')
B11_2013 = images.select('0_B11')
B1_2014 = images.select('1_B1')
B2_2014 = images.select('1_B2')
B3_2014 = images.select('1_B3')
B4_2014 = images.select('1_B4')
B5_2014 = images.select('1_B5')
B6_2014 = images.select('1_B6')
B7_2014 = images.select('1_B7')
B8_2014 = images.select('1_B8')
B9_2014 = images.select('1_B9')
B10_2014 = images.select('1_B10')
B11_2014 = images.select('1_B11')
and so on ...
B11_2020 = images.select('7_B11')
Ultimately, from these lines of code, I need to generate a list of variables (my_variables) that I can pass off to a function. For example:
my_variables = [B1_2013, B2_2013, B3_2013, B4_2013, B5_2013, B6_2013, B7_2013, B8_2013, B9_2013, B10_2013, B11_2013, \
B1_2014, B2_2014, B3_2014, B4_2014, B5_2014, B6_2014, B7_2014, B8_2014, B9_2014, B10_2014, B11_2014]
Is there a more efficient approach to automatically generate hundreds of lines of code (e.g. B1_2013 = images.select('0_B1') and so on...) following the first code example so that I can automatically generate a list of variables in the second code example (e.g. my_variables = [B1_2013, and so on...]?
Just make a list using a loop or list comprehension.
my_images = [images.select(f'{i}_B{j}') for i in range(8) for j in range(12)]
In this use case it is more viable to use a dict to store the "variables" it is not good practice to dynamically build variables. Below is an example using itertools.product that will build a dict with desired output:
from itertools import product
images = {f'B{i}_{y+2013}': images.select(f'{y}_B{i}')
for y, i in product(range(12), range(1, 8))}
Result:
{'B1_2013': '0_B1',
'B2_2013': '0_B2',
'B3_2013': '0_B3',
'B4_2013': '0_B4',
'B5_2013': '0_B5',
'B6_2013': '0_B6',
'B7_2013': '0_B7',
'B1_2014': '1_B1',
'B2_2014': '1_B2',
'B3_2014': '1_B3',
...
}
Then to access the desired "variable" use:
>>> images['B3_2014']
'1_B1'
#Barmar's answer is correct. You can extend his answer if you wanted to index the variables by doing the following:
my_images = {f'{i}_B{j}':images.select(f'{i}_B{j}') for i in range(8) for j in range(12)}
This is called dictionary comprehension.
Or dictionary comprehension:
my_images = {'B{j}_{2013 + i}': images.select(f'{i}_B{j}') for i in range(8) for j in range(12)}
Refer them with:
my_images['B1_2013']
my_images['B2_2013']
...

Is there a faster/better way to do an iterative list intersection?

I'm trying to get a list of credit for any given opportunity ('opp') exclusive to the maximal combinations of 'touches' in my test DataFrame.
So for every combination of touches, I get the intersection of all unique opps (intersect_list).
Then I remove the opp if it also exists in a superset (remove_common_elements)
I'm encountering a really long run time doing this with real data, but i can't figure out a better way to do it. The intersect_list is what takes the longest by far (several hours for ~65k entries of real data, where any given nested list has < 10 elements)
I can't figure out how to do an apply or list comprehension, etc...or other way to speed this up.
test = pd.DataFrame(data={'opp':['a','a','a','b','b','c','a','b','c','d'],'touch':['z','y','x','y','z','x','z','y','x','z']})
touches = test['touch'].unique().tolist()
test_array_indices = list(range(0,len(touches)))
test_array_combos = []
for i in range(1,len(touches)+1):
test_array_combos.extend(combinations(test_array_indices,i))
def intersect_list(list1, list2):
result = [i for i in list1 if i in list2]
return result
def remove_common_elements(list1,list2):
result = [i for i in list1 if i not in list2]
return result
k = []
for i in range(0,len(touches)):
k.append(test[test['touch'] == touches[i]]['opp'].unique().tolist())
test_opp_list = []
for j in range(0,len(test_array_combos)):
t = []
for i in range(0,len(test_array_combos[j])):
t.append(k[test_array_combos[j][i]])
test_opp_list.append(t)
list_t = []
for i in range(0,len(test_opp_list)):
list_t.append([])
for i in range(0,len(test_opp_list)):
list_t[i] = test_opp_list[i][0]
for j in range(0,len(test_opp_list[i])):
list_t[i] = intersect_list(list_t[i],test_opp_list[i][j])
for i in range(0,len(list_t)-1):
for j in range(1, len(list_t)-i):
list_t[i] = remove_common_elements(list_t[i], list_t[i+j])
The best thing I found so far is to turn the list of lists into a list or sets. This speeds things up by about 4x for my tiny data set, but as I understand the difference grows exponentially with size.
test = pd.DataFrame(data={'opp':['a','a','a','b','b','c','a','b','c','d'],'touch':['z','y','x','y','z','x','z','y','x','z']})
touches = test['touch'].unique().tolist()
k = []
for i in range(0,len(touches)):
k.append(set(test[test['touch'] == touches[i]]['opp'].unique().tolist()))
test_array_indices = list(range(0,len(touches)))
test_array_combos = []
for i in range(1,len(touches)+1):
test_array_combos.extend(combinations(test_array_indices,i))
test_opp_list_sets = []
for j in range(0,len(test_array_combos)):
t = []
for i in range(0,len(test_array_combos[j])):
t.append(k[test_array_combos[j][i]])
test_opp_list_sets.append(t)
list_s = []
for i in range(0,len(test_opp_list_sets)):
list_s.append([])
for i in range(0, len(test_opp_list_sets)):
list_s[i] = test_opp_list_sets[i][0].intersection(*test_opp_list_sets[i])
for i in range(0,len(list_s)-1):
for j in range(1, len(list_s)-i):
list_s[i] = list_s[i] - list_s[i+j]

How can I optimize the groupby.apply(function) in Python?

I have a function that uses deque.collections to track daily stock in based on FIFO. An order will be fulfilled if possible and is substracted from stock accordingly. I use a function in groupby.apply(my_function).
I have struggles where to place the second loop. Both loops work properly when run on their own. But I do not get them working combined.
The dataset is about 1.5 million rows.
Thanks.
DOS = 7
WIP = 1
df_fin['list_stock'] = 0
df_fin['stock_new'] = 0
def create_stocklist(x):
x['date_diff'] = x['dates'] - x['dates'].shift()
x['date_diff'] = x['date_diff'].fillna(0)
x['date_diff'] = (x['date_diff'] / np.timedelta64(1, 'D')).astype(int)
x['list_stock'] = x['list_stock'].astype(object)
x['stock_new'] = x['stock_new'].astype(object)
var_stock = DOS*[0]
sl = deque([0],maxlen=DOS)
for i in x.index:
order = x['order_bin'][i]
if x['date_diff'][i] > 0:
for p in range(0,x['date_diff'][i]):
if p == WIP:
sl.appendleft(x.return_bin[i-1])
else:
sl.appendleft(0)
sl_list = list(sl)
sl_list.reverse()
new_list = []
#from here the loop does not work as I wanted it to work.
#I want to loop over de created sl_list
#and then start the loop above with the outcome of the loop below.
for elem in sl_list:
while order > 0:
val = max(0,elem-order)
order = (abs(min(0,elem-order)))
new_list.append(val)
break
else:
new_list.append(elem)
new_list.reverse()
x.at[i,'list_stock'] = new_list
sl = deque(new_list)
return x
df_fin.groupby(by=['ID']).apply(create_stocklist)
You do not have access to sl_list inside the second loop, you should just define it in the upper scope: for example just after the first global for loop:
for i in x.index:
# define it just here
sl_list = []
order = x['order_bin'][i]

Python -- using regex on a class instance

I have a class that was taking in lists of 1's and 0's and performing GF(2) finite field arithmetic operations. It used to work until I tried to make it take the input in polynomial format. As for how the finite arithmetic will be done after fixing the regex issue, I was thinking about overloading the operators.
The actual code in parsePolyToListInput(input) works when outside the class. The problem seems to be in the regex, which errors that it will only take in a string (this makes sense), but does not seem to initialize with self.expr as a parameter (that's a problem). The #staticmethod just before the initialization was an attempt to salvage the unbound error as it the polynomial was passed in, but this is apparently completely wrong. Just to save you time if you decide to look at any of the arithmetic operations, modular inverse does not work (seems to be due to the formatting issue after every iteration of that while loop for division in the function and what the return type is):
import re
class gf2poly:
#binary arithemtic on polynomials
##staticmethod
def __init__(self,expr):
self.expr = expr
#self.expr = [int(i) for i in expr]
self.expr = gf2poly.parsePolyToListInput(self.expr)
def convert(self): #to clarify the input if necessary
convertToString = str(self.expr)
print "expression is %s"%(convertToString)
def id(self): #returns modulus 2 (1,0,0,1,1,....) for input lists
return [int(self.expr[i])%2 for i in range(len(self.expr))]
def listToInt(self): #converts list to integer for later use
result = gf2poly.id(self)
return int(''.join(map(str,result)))
def prepBinary(a,b): #converts to base 2 and orders min and max for use
a = gf2poly.listToInt(a); b = gf2poly.listToInt(b)
bina = int(str(a),2); binb = int(str(b),2)
a = min(bina,binb); b = max(bina,binb);
return a,b
#staticmethod
def outFormat(raw):
raw = str(raw[::-1]); g = [] #reverse binary string for enumeration
[g.append(i) for i,c in enumerate(raw) if c == '1']
processed = "x**"+' + x**'.join(map(str, g[::-1]))
if len(g) == 0: return 0 #return 0 if list empty
return processed #returns result in gf(2) polynomial form
def parsePolyToListInput(poly):
c = [int(i.group(0)) for i in re.finditer(r'\d+', poly)] #re.finditer returns an iterator
#m = max(c)
return [1 if x in c else 0 for x in xrange(max(c), -1, -1)]
#return d
def add(self,other): #accepts 2 lists as parameters
a = gf2poly.listToInt(self); b = gf2poly.listToInt(other)
bina = int(str(a),2); binb = int(str(b),2)
m = bina^binb; z = "{0:b}".format(m)
return z #returns binary string
def subtract(self,other): #basically same as add() but built differently
result = [self.expr[i] ^ other.expr[i] for i in range(len(max(self.expr,other.expr)))]
return int(''.join(map(str,result)))
def multiply(a,b): #a,b are lists like (1,0,1,0,0,1,....)
a,b = gf2poly.prepBinary(a,b)
g = []; bitsa = "{0:b}".format(a)
[g.append((b<<i)*int(bit)) for i,bit in enumerate(bitsa)]
m = reduce(lambda x,y: x^y,g); z = "{0:b}".format(m)
return z #returns product of 2 polynomials in gf2
def divide(a,b): #a,b are lists like (1,0,1,0,0,1,....)
a,b = gf2poly.prepBinary(a,b)
bitsa = "{0:b}".format(a); bitsb = "{0:b}".format(b)
difflen = len(str(bitsb)) - len(str(bitsa))
c = a<<difflen; q=0
while difflen >= 0 and b != 0: #a is divisor, b is dividend, b/a
q+=1<<difflen; b = b^c # b/a because of sorting in prep
lendif = abs(len(str(bin(b))) - len(str(bin(c))))
c = c>>lendif; difflen -= lendif
r = "{0:b}".format(b); q = "{0:b}".format(q)
return r,q #returns r remainder and q quotient in gf2 division
def remainder(a,b): #separate function for clarity when calling
r = gf2poly.divide(a,b)[0]; r = int(str(r),2)
return "{0:b}".format(r)
def quotient(a,b): #separate function for clarity when calling
q = gf2poly.divide(a,b)[1]; q = int(str(q),2)
return "{0:b}".format(q)
def extendedEuclideanGF2(a,b): # extended euclidean. a,b are GF(2) polynomials in list form
inita,initb=a,b; x,prevx=0,1; y,prevy = 1,0
while sum(b) != 0:
q = gf2poly.quotient(a,b);
q = list(q); q = [int(x) for x in q]
#q = list(q);
#q = tuple([int(i) for i in q])
q = gf2poly(q)
a,b = b,gf2poly.remainder(a,b);
#a = map(list, a);
#b = [list(x) for x in a];
#a = [int(x) for x in a]; b = [int(x) for x in b];
b = list(b); b = [int(x) for x in b]
#b = list(b);
#b = tuple([int(i) for i in b])
b = gf2poly(b)
#x,prevx = (prevx-q*x, x);
#y,prevy=(prevy-q*y, y)
print "types ",type(q),type(a),type(b)
#q=a//b; a,b = b,a%b; x,prevx = (prevx-q*x, x); y,prevy=(prevy-q*y, y)
#print("%d * %d + %d * %d = %d" % (inita,prevx,initb,prevy,a))
return a,prevx,prevy # returns gcd of (a,b), and factors s and t
def modular_inverse(a,mod): # where a,mod are GF(2) polynomials in list form
gcd,s,t = gf2poly.extendedEuclideanGF2(a,mod); mi = gf2poly.remainder(s,mod)
#gcd,s,t = ext_euc_alg_i(a,mod); mi = s%mod
if gcd !=1: return False
#print ("%d * %d mod %d = 1"%(a,mi,mod))
return mi # returns modular inverse of a,mod
I usually test it with this input:
a = x**14 + x**1 + x**0
p1 = gf2poly(a)
b = x**6 + x**2 + x**1
p2 = gf2poly(b)
The first thing you might notice about my code is that it's not very good. There are 2 reasons for that:
1) I wrote it so that the 1st version could do work in the finite field GF(2), and output in polynomial format. Then the next versions were supposed to be able to take polynomial inputs, and also perform the crucial 'modular inverse' function which is not working as planned (this means it's actually not working at all).
2) I'm teaching myself Python (I'm actually teaching myself programming overall), so any constructive criticism from pro Python programmers is welcome as I'm trying to break myself of beginner habits as quickly as possible.
EDIT:
Maybe some more of the code I've been testing with will help clarify what works and what doesn't:
t1 = [1,1,1]; t2 = [1,0,1]; t3 = [1,1]; t4 = [1, 0, 1, 1, 1, 1, 1]
t5 = [1,1,1,1]; t6 = [1,1,0,1]; t7 = [1,0,1,1,0]
f1 = gf2poly(t1); f2 = gf2poly(t2); f3 = gf2poly(t3); f4 = gf2poly(t4)
f5 = gf2poly(t5);f6 = gf2poly(t6);f7 = gf2poly(t7)
##print "subtract: ",a.subtract(b)
##print "add: ",a.add(b)
##print "multiply: ",gf2poly.multiply(f1,f3)
##print "multiply: ",gf2poly.multiply(f1,f2)
##print "multiply: ",gf2poly.multiply(f3,f4)
##print "degree a: ",a.degree()
##print "degree c: ",c.degree()
##print "divide: ",gf2poly.divide(f1,b)
##print "divide: ",gf2poly.divide(f4,a)
##print "divide: ",gf2poly.divide(f4,f2)
##print "divide: ",gf2poly.divide(f2,a)
##print "***********************************"
##print "quotient: ",gf2poly.quotient(f2,f5)
##print "remainder: ",gf2poly.remainder(f2,f5)
##testq = gf2poly.quotient(f4,f2)
##testr = gf2poly.remainder(f4,f2)
##print "quotient: ",testq,type(testq)
##print "remainder: ",testr,type(testr)
##print "***********************************"
##print "outFormat testp: ",gf2poly.outFormat(testq)
##print "outFormat testr: ",gf2poly.outFormat(testr)
##print "***********************************"
#print "gf2poly.modular_inverse(): ",gf2poly.modular_inverse(f2,f3)
print "p1 ",p1 #,type(f2),type(f3)
#print "parsePolyToListInput ",gf2poly.parsePolyToListInput(a)
Part of your problem is that you haven't declared self as an argument for parsePolyToListInput. When you call a method, the instance you call it on is implicitly bound as the first argument. Naming the first argument self is a convention, not a strict requirement - the instance is being bound to poly, which you then try to run a regexp over.
It looks me like there's some confusion in your design here about what's behavior of individual instances of the class and what's class-level or module-level behavior. In Python, it's perfectly acceptable to leave something that doesn't take an instance of a class as a parameter defined as a module-level function rather than shoehorning it in awkwardly. parsePolyToListInput might be one such function.
Your add implementation, similarly, has a comment saying it "accepts 2 lists as parameters". In fact, it's going to get a gf2poly instance as its first argument - this is probably right if you're planning to do operator overloading, but it means the second argument should also be a gf2poly instance as well.
EDIT:
Yeah, your example code shows a breakdown between class behavior and instance behavior. Either your multiply call should look something like this:
print "multiply: ",f1.multiply(f3)
Or multiply shouldn't be a method at all:
gfpoly.py:
def multiply(f1, f2):
a,b = prepBinary(a,b)
g = []; bitsa = "{0:b}".format(a)
[g.append((b<<i)*int(bit)) for i,bit in enumerate(bitsa)]
m = reduce(lambda x,y: x^y,g); z = "{0:b}".format(m)
return z #returns product of 2 polynomials in gf2
That latter approach is, for instance, how the standard math library does things.
The advantage of defining a multiplication method is that you could name it appropriately (http://docs.python.org/2/reference/datamodel.html#special-method-names) and use it with the * operator:
print "multiply: ",f1 *f3

Categories