For loop returning odd values - python

I have two lists I want to iterate through:
efw = [13.882352941176457, 10.854092526690406, 94.25675675675676, 17.851739788199694, 14.63844797178131, 8.166189111747846, 5.278592375366564, 3.4129692832764347, -6.413612565445015, 11.678832116788328, 23.859649122807003, 4.545454545454564, 10.105580693815996, -3.562340966921118, -0.6684491978609763, 2.285714285714291, 8.505747126436791]
and
gini = [3.9215686274509887, 6.190476190476191, -7.733812949640296, -16.608391608391603, -13.458262350936979, 7.505518763796926, -12.884615384615394, -20.21276595744681, -19.839679358717433, -10.885608856088568, -12.891986062717764, -15.56420233463035, -12.66540642722116, -12.802768166089962, -11.336032388663975, -13.507625272331147, -1.882845188284521]
I want to create two new lists with + and - depending on the values in gini and efw. If the value in gini is positive, then a + should be added to the g list. Same with the e and efw lists. I have tried:
g = []
e = []
for n in gini:
if n > 0:
g.append("+")
g.append("-")
for f in efw:
if f > 0:
e.append("+")
e.append("-")
But for some positive values in gini there is a - sign... Why is the for loop appending the wrong symbols to the new lists?

Adding else solved it.
g = []
e = []
for n in gini:
if n > 0:
g.append("+")
else:
g.append("-")
for f in efw:
if f > 0:
e.append("+")
else:
e.append("-")

Related

IndexError: too many indices for array: array is 1-dimensional, but 2 were indexed. Works for first two loops

Let me start by saying that I know this error message has posts about it, but I'm not sure what's wrong with my code. The block of code works just fine for the first two loops, but then fails. I've even tried removing the first two loops from the data to rule out issues in the 3rd loop, but no luck. I did have it set to print out the unsorted temporary list, and it just prints an empty array for the 3rd loop.
Sorry for the wall of comments in my code, but I'd rather have each line commented than cause confusion over what I'm trying to accomplish.
TL;DR: I'm trying to find and remove outliers from a list of data, but only for groups of entries that have the same number in column 0.
Pastebin with data
import numpy as np, csv, multiprocessing as mp, mysql.connector as msc, pandas as pd
import datetime
#Declare unsorted data array
d_us = []
#Declare temporary array for use in loop
tmp = []
#Declare sorted data array
d = []
#Declare Sum variable
tot = 0
#Declare Mean variable
m = 0
#declare sorted final array
sort = []
#Declare number of STDs
t = 1
#Declare Standard Deviation variable
std = 0
#Declare z-score variable
z_score
#Timestamp for output files
nts = datetime.datetime.now().timestamp()
#Create output file
with open(f"calib_temp-{nts}.csv", 'w') as ctw:
pass
#Read data from CSV
with open("test.csv", 'r', newline='') as drh:
fr_rh = csv.reader(drh, delimiter=',')
for row in fr_rh:
#append data to unsorted array
d_us.append([float(row[0]),float(row[1])])
#Sort array by first column
d = np.sort(d_us)
#Calculate the range of the data
l = round((d[-1][0] - d[0][0]) * 10)
#Declare the starting value
s = d[0][0]
#Declare the ending value
e = d[-1][0]
#Set the while loop counter
n = d[0][0]
#Iterate through data
while n <= e:
#Create array with difference column
for row in d:
if row[0] == n:
diff = round(row[0] - row[1], 1)
tmp.append([row[0],row[1],diff])
#Convert to numpy array
tmp = np.array(tmp)
#Sort numpy array
sort = tmp[np.argsort(tmp[:,2])]
#Calculate sum of differences
for row in tmp:
tot = tot + row[2]
#Calculate mean
m = np.mean(tot)
#Calculate Standard Deviation
std = np.std(tmp[:,2])
#Calculate outliers and write to output file
for y in tmp:
z_score = (y[2] - m)/std
if np.abs(z_score) > t:
with open(f"calib_temp-{nts}.csv", 'a', newline='') as ct:
c = csv.writer(ct, delimiter = ',')
c.writerow([y[0],y[1]])
#Reset Variables
tot = 0
m = 0
n = n + 0.1
tmp = []
std = 0
z_score = 0
Do this before the loop:
#Create output file
ct = open(f"calib_temp-{nts}.csv", 'w')
c = csv.writer(ct, delimiter = ',')
Then change the loop to this. Note that I have moved your initializations to the top of the loop, so you don't need to initialize them twice. Note the if tmp: line, which solves the numpy exception.
#Iterate through data
while n <= e:
tot = 0
m = 0
tmp = []
std = 0
z_score = 0
#Create array with difference column
for row in d:
if row[0] == n:
diff = round(row[0] - row[1], 1)
tmp.append([row[0],row[1],diff])
#Sort numpy array
if tmp:
#Convert to numpy array
tmp = np.array(tmp)
sort = tmp[np.argsort(tmp[:,2])]
#Calculate sum of differences
for row in tmp:
tot = tot + row[2]
#Calculate mean
m = np.mean(tot)
#Calculate Standard Deviation
std = np.std(tmp[:,2])
#Calculate outliers and write to output file
for y in tmp:
z_score = (y[2] - m)/std
if np.abs(z_score) > t:
c.writerow([y[0],y[1]])
#Reset Variables
n = n + 0.1

How to create the smallest possible number remaining zeros?

I was given a task to create the smallest number from two numbers remaining zeros.
But I cannot solve the task because of my code is not remaining all zeros appropriate. If the input is
245
36
the output is 23456 and that's correct. But with input:
40
305
it outputs: [0,0,3,4,5]. But should be 30045.
Here's my code:
f1 = [int(x) for x in input()]
f2 = [int(y) for y in input()]
f = f1+f2
for each in range(len(f)):
for eacc in range(each+1, len(f)):
if f[each] > f[eacc]:
f[each], f[eacc] = f[eacc], f[each]
for zero in range(len(f)):
if f[zero] == 0 and f[0] > 0:
f.remove(0)
f.insert(zero+1, 0)
break
print(f)
n1 = 40
n2 = 305
# sort lexicograhically
ns = sorted(str(n1) + str(n2))
# move the first non-zero element to the start
i = ns.count('0')
if 0 < i < len(ns):
ns[0:0] = ns.pop(i)
Remove all the zeros. Get all the permutations and find the min. Then add zero from index 1
from itertools import permutations
a=list('40')+list('305')
a=list(map(int,a))
num_of_zero=a.count(0) # get the count of zeros
for i in range(num_of_zero):
a.pop(a.index(0))
new_list=list(min(list(permutations(a)))) # get all the permutations
for i in range(num_of_zero):
new_list.insert(1,0) # insert zeros at index 1 shifting all element to the right
print(''.join(map(str,new_list)))#30045
Without permutations sorted will also work
a=list('40')+list('305')
a=list(map(int,a))
num_of_zero=a.count(0)
for i in range(num_of_zero):
a.pop(a.index(0))
new_list=sorted(a)
for i in range(num_of_zero):
new_list.insert(1,0)
print(''.join(map(str,new_list)))#30045
Using numpy
import numpy as np
a=list('40')+list('305')
a=list(map(int,a))
num_of_zero=a.count(0)
new_list=sorted(a) # sorted will return [0,0,3,4,5]
I = np.nonzero(new_list) #return non_zero_array
if(len(I[0])>0):
first_non_zero_value=new_list.pop(I[0][0]) #get index of first element
new_list.insert(0,first_non_zero_value)
print(''.join(map(str,new_list)))#30045
Here you could use itertools.permutations. First I would use map to change the ints to lists. Next I would concatenate them and have one list of 5 ints. Then using permutations we could generate all possible numbers that could be made from these 5 ints. From our new list we could now take the min using *list comprehension to filter out any item that begins with 0 using if i[0]. Since it is a tuple we have to convert the elements to str then we can join them into an int and print
from itertools import permutations
a = 40
b = 305
a = [*map(int, str(a))]
b = [*map(int, str(b))]
c = a + b
combo = list(permutations(c, len(c)))
res = min([i for i in combo if i[0]])
res = [str(i) for i in res]
print(''.join(res))
# 30045
If a = 0, b = 0 is a potential input, a try/except block would be neccessary
try:
res = min([i for i in combo if i[0]])
res = [str(i) for i in res]
print(int(''.join(res)))
except ValueError:
res = 0
print(res)

how to optimize this code and algorithm?

def compute_qty(self):
prduct = self.env["product.product"]
attribute = self.env["product.attribute.value"]
for line in self.qty_line_id:
stake_meter = line.pipe_size
line_qty = line.pipe_qty
pipe_list = []
qty_list = []
pipe_size_qty_list = []
pipe_size_qty_list_of_list = []
for obj in prduct.search([('product_tmpl_id','=',line.product_id.product_tmpl_id.id),('qty_available','>', 0)]):
for attr in obj.attribute_value_ids.ids:
for name in attribute.search([('id','=', str(attr))]):
pipe_product_size_qty_list = []
if float(str(name.name)) >= line.pipe_size:
pipe_size_qty_list.append(float(str(name.name)))
pipe_size_qty_list.append(obj.qty_available)
pipe_size_qty_list_of_list.append(pipe_size_qty_list)
pipe_size_qty_list = []
pipe_size_qty_list_of_list = sorted(pipe_size_qty_list_of_list)
i = 0
n = line_qty
t = 0
while n !=0 and i < len(pipe_size_qty_list_of_list):
pipe_qty_need = math.floor(float(pipe_size_qty_list_of_list[i][0] / pipe_meter))
if pipe_qty_need == 1 and pipe_size_qty_list_of_list[i][0] > pipe_meter:
if pipe_size_qty_list_of_list[i][1] <= n:
pipe_size = pipe_size_qty_list_of_list[i][0]
pipe_qty = pipe_size_qty_list_of_list[i][1]
pipe_list.append(pipe_size)
qty_list.append(pipe_qty)
if pipe_size_qty_list_of_list[i][1] > n:
pipe_size= pipe_size_qty_list_of_list[i][0]
pipe_qty= n
pipe_list.append(pipe_size)
qty_list.append(pipe_qty)
break
n= n - pipe_qty
t = t + pipe_qty
i += 1
if pipe_qty_need !=1 and pipe_size_qty_list_of_list[i][0] > pipe_meter:
if pipe_qty_need * pipe_size_qty_list_of_list[i][1] <= n:
pipe_size= pipe_size_qty_list_of_list[i][0]
pipe_qty= pipe_size_qty_list_of_list[i][1]
pipe_list.append(pipe_size)
qty_list.append(pipe_qty)
if pipe_qty_need * pipe_size_qty_list_of_list[i][1] > n:
pipe_size= pipe_size_qty_list_of_list[i][0]
pipe_qty=math.ceil(float(n/pipe_qty_need))
pipe_list.append(pipe_size)
qty_list.append(pipe_qty)
break
n= n - pipe_qty
t = t + pipe_qty
i += 1
raise UserError(_("pipe Test list %s")%(qty_list)) #here is the chosen quantity from the suitable size
im going to compute the quantity of possible length of pipe i can use to build a
new object, i had to pick pipes from the stock depends
on the size of the new object, for example:
- suppose i need 5 pipe of size "4.3" meter to build a new object:
- what i realy have in the stock:
- 1 pipe of size 5
- 4 pipe of size 4.1
- 2 pipe of size 4.4
- 10 pipe of size 9
cutting is possible while assembeling is not.
so here i should pick from the available quantity of size >= 4.3 sequentially from the smallest to the largest
until the quatity i need is equal to 5 "the number of needed pipe"
from the exampe above i have to chose the following pipe:
2 of "4.4"
1 of "5"
1 of "9" (here becaue it's sufficeint to produce 2 of (4.3) pipe)
what i actually did is appending pipe's size and quantity in a list of list in the form [[size,qty]] ,sorting and searching on that list.
here is the list:
[[4.4,2],[5,1],[9,10]]
what i should get from that list is the possible size and quantity
[[4.4,2],[5,1][9,1]]
it's work fine but im looking for optimizing my code.
thanks in advance

How to reduce a collection of ranges to a minimal set of ranges [duplicate]

This question already has answers here:
Union of multiple ranges
(5 answers)
Closed 7 years ago.
I'm trying to remove overlapping values from a collection of ranges.
The ranges are represented by a string like this:
499-505 100-115 80-119 113-140 500-550
I want the above to be reduced to two ranges: 80-140 499-550. That covers all the values without overlap.
Currently I have the following code.
cr = "100-115 115-119 113-125 80-114 180-185 500-550 109-120 95-114 200-250".split(" ")
ar = []
br = []
for i in cr:
(left,right) = i.split("-")
ar.append(left);
br.append(right);
inc = 0
for f in br:
i = int(f)
vac = []
jnc = 0
for g in ar:
j = int(g)
if(i >= j):
vac.append(j)
del br[jnc]
jnc += jnc
print vac
inc += inc
I split the array by - and store the range limits in ar and br. I iterate over these limits pairwise and if the i is at least as great as the j, I want to delete the element. But the program doesn't work. I expect it to produce this result: 80-125 500-550 200-250 180-185
For a quick and short solution,
from operator import itemgetter
from itertools import groupby
cr = "499-505 100-115 80-119 113-140 500-550".split(" ")
fullNumbers = []
for i in cr:
a = int(i.split("-")[0])
b = int(i.split("-")[1])
fullNumbers+=range(a,b+1)
# Remove duplicates and sort it
fullNumbers = sorted(list(set(fullNumbers)))
# Taken From http://stackoverflow.com/questions/2154249
def convertToRanges(data):
result = []
for k, g in groupby(enumerate(data), lambda (i,x):i-x):
group = map(itemgetter(1), g)
result.append(str(group[0])+"-"+str(group[-1]))
return result
print convertToRanges(fullNumbers)
#Output: ['80-140', '499-550']
For the given set in your program, output is ['80-125', '180-185', '200-250', '500-550']
Main Possible drawback of this solution: This may not be scalable!
Let me offer another solution that doesn't take time linearly proportional to the sum of the range sizes. Its running time is linearly proportional to the number of ranges.
def reduce(range_text):
parts = range_text.split()
if parts == []:
return ''
ranges = [ tuple(map(int, part.split('-'))) for part in parts ]
ranges.sort()
new_ranges = []
left, right = ranges[0]
for range in ranges[1:]:
next_left, next_right = range
if right + 1 < next_left: # Is the next range to the right?
new_ranges.append((left, right)) # Close the current range.
left, right = range # Start a new range.
else:
right = max(right, next_right) # Extend the current range.
new_ranges.append((left, right)) # Close the last range.
return ' '.join([ '-'.join(map(str, range)) for range in new_ranges ]
This function works by sorting the ranges, then looking at them in order and merging consecutive ranges that intersect.
Examples:
print(reduce('499-505 100-115 80-119 113-140 500-550'))
# => 80-140 499-550
print(reduce('100-115 115-119 113-125 80-114 180-185 500-550 109-120 95-114 200-250'))
# => 80-125 180-185 200-250 500-550

How to cycle through the index of an array?

line 14 is where my main problem is.i need to cycle through each item in the array and use it's index to determine whether or not it is a multiple of four so i can create proper spacing for binary numbers.
def decimalToBinary(hu):
bits = []
h = []
while hu > 0:
kla = hu%2
bits.append(kla)
hu = int(hu/2)
for i in reversed(bits):
h.append(i)
if len(h) <= 4:
print (''.join(map(str,h)))
else:
for j in range(len(h)):
h.index(1) = h.index(1)+1
if h.index % 4 != 0:
print (''.join(map(str,h)))
elif h.index % 4 == 0:
print (' '.join(map(str,h)))
decimalToBinary( 23 )
If what you're looking for is the index of the list from range(len(h)) in the for loop, then you can change that line to for idx,j in enumerate(range(len(h))): where idx is the index of the range.
This line h.index(1) = h.index(1)+1 is incorrect. Modified your function, so at least it executes and generates an output, but whether it is correct, i dont know. Anyway, hope it helps:
def decimalToBinary(hu):
bits = []
h = []
while hu > 0:
kla = hu%2
bits.append(kla)
hu = int(hu/2)
for i in reversed(bits):
h.append(i)
if len(h) <= 4:
print (''.join(map(str,h)))
else:
for j in range(len(h)):
h_index = h.index(1)+1 # use h_index variable instead of h.index(1)
if h_index % 4 != 0:
print (''.join(map(str,h)))
elif h_index % 4 == 0:
print (' '.join(map(str,h)))
decimalToBinary( 23 )
# get binary version to check your result against.
print(bin(23))
This results:
#outout from decimalToBinary
10111
10111
10111
10111
10111
#output from bin(23)
0b10111
You're trying to join the bits to string and separate them every 4 bits. You could modify your code with Marcin's correction (by replacing the syntax error line and do some other improvements), but I suggest doing it more "Pythonically".
Here's my version:
def decimalToBinary(hu):
bits = []
while hu > 0:
kla = hu%2
bits.append(kla)
hu = int(hu/2)
h = [''.join(map(str, bits[i:i+4])) for i in range(0,len(bits),4)]
bu = ' '.join(h)
print bu[::-1]
Explanation for the h assignment line:
range(0,len(bits),4): a list from 0 to length of bits with step = 4, eg. [0, 4, 8, ...]
[bits[i:i+4] for i in [0, 4, 8]: a list of lists whose element is every four elements from bits
eg. [ [1,0,1,0], [0,1,0,1] ...]
[''.join(map(str, bits[i:i+4])) for i in range(0,len(bits),4)]: convert the inner list to string
bu[::-1]: reverse the string
If you are learning Python, it's good to do your way. As #roippi pointed out,
for index, value in enumerate(h):
will give you access to both index and value of member of h in each loop.
To group 4 digits, I would do like this:
def decimalToBinary(num):
binary = str(bin(num))[2:][::-1]
index = 0
spaced = ''
while index + 4 < len(binary):
spaced += binary[index:index+4]+' '
index += 4
else:
spaced += binary[index:]
return spaced[::-1]
print decimalToBinary(23)
The result is:
1 0111

Categories