elif in list comprehension using python conditionals - list-comprehension

for example
for p in list(extracted_data):
if (p >= 80):
print ('orange')
elif(80 > p >= 60):
print ('red')
else:
print('yellow')
Is there any list comprehension for the same.

you can do like this
x = [ 'orange' if p>=80 else 'red' if 80>p >=60 else 'yellow' for p in list(extacted_data)]

Readability and reusability ?
Chances are your business logic will need to be used in more than one place. Why not create a function that determines the color, then use list comprehension to create your list?
def colors(x):
retval = 'yellow'
if (x >= 80):
retval = 'orange'
elif(80 > x >= 60):
retval = 'red'
return retval
print([colors(x) for x in extracted_data])
Output
['orange', 'orange', 'red', 'yellow']

Related

randomly select two position in a file and swap words

I want to select n pairs of word positions (unique) in a file and swap them. My code is as following, but it never gives me n pairs I am looking for.
My logic is first to sample 2*n elements and create n pairs. Then iterate over the file contents (stored in list) and locate the correct positions and make the swap. It is not working. I have difficulty in understanding where it fails.
with open(rname) as rd:
lines = rd.readlines()
for i in range(len(lines)):
lines[i] = lines[i].strip()
sz = sum(len(x.split()) for x in lines)
chosen = random.sample(range(sz),6000)
result = pairwise(chosen)
for (a,b) in result:
flag1 = 0
flag2 = 0
l = 0
ind1 = 0
m = 0
ind2 = 0
j = 0
for y in range(len(lines)):
if ( (j+len(lines[y].split()) >= a) and (flag1 == 0)):
l = y
ind1 = a - j-1
flag1 = 1
if ( (j+len(lines[y].split()) >= b) and (flag2 == 0)):
m = y
ind2 = b - j-1
flag2 = 1
if ( (flag1 == 1) and (flag2 == 1)):
words1 = lines[l].split()
words2 = lines[m].split()
words1[ind1], words2[ind2] = 'swapped'+words2[ind2], 'swapped'+words1[ind1]
lines[l] = ' '.join(words1)
lines[m] = ' '.join(words2)
break
j += len(lines[y].split())
name ='n_file.txt'
with open(wname,'w') as wd:
for line in lines:
print(line, file=wd)
def pairwise(iterable):
a, b = tee(iterable)
next(b, None)
return zip(a, b)
For example, consider a file with content
i am here, where are you
it is none of your business
Let us say i choose 2 positions (2,8) (position is defined in terms of the word positions in the file and start with 0 for the first word in the file). My output will look like
i am swappednone where are you
it is swappedhere, of your business
Not a complete solution, but this might give you some ideas:
import random
def swap_pairs(items,n):
"""swaps n distinct pairs of objects in items"""
k = len(items)
indices = random.sample(range(k),2*n)
random.shuffle(indices)
for i in range(n):
s, t = indices[2*i], indices[2*i+1]
items[s], items[t] = items[t], items[s]
This mutates the list in place.
For example, if
words = ['i', 'am', 'here,', 'where', 'are', 'you', 'it', 'is', 'none', 'of', 'your', 'business']
then after
swap_pairs(words,3)
words might be
['you', 'am', 'it', 'none', 'are', 'i', 'here,', 'is', 'where', 'of', 'your', 'business']

I am writing a code based on some formulas;but my if statement does not seem to work(line 33)

W = int(input('Enter weight:'))
b = [1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0]
AR = [1, 2, 3, 4, 5]
T = [50.99238, 50.05062, 49.07943, 48.05919, 47.00952, 45.92061, 44.79246, 43.62507, 42.42825, 41.18238, 39.90708, 38.60235, 37.24857, 35.86536, 34.4331, 32.97141, 31.48029, 29.94012, 28.37052, 26.76168, 25.1136]
CL = [1.0]
CD = [0.5]
clmax = 2
n = 0
z = 0
while b[n] < 2.1 :
while AR[z]< 5.1:
cl = CL[n]
cd = CD[z]
s = ((b[n]*b[n])/AR[z])
V = ((2*W*9.81)/(1.2*s*clmax) ** 0.5)*1.1
vlof = V/1.41
Vlof = round(vlof)
D = 0.5*cd*1.2*Vlof*Vlof*s
L = 0.5*cl*1.2*Vlof*Vlof*s
a = (9.81/W)*(T[Vlof]-D-O.O5(W-L))
Sg = (V*V)/(2*a)
if Sg <= 30:
print('IT WILL TAKEOFF')
else:
print('It will NOT takeoff')
t/c = int(input('t/c ratio is:'))
l = int(input('Taper ratio is:'))
f = 0.005(1+1.5*((l-0.6)**2))
e = (1/((1+0.12*V*V*0.003*0.003)(1+(0.142+(f*AR[z]*(10*t/c)**0.33)
+(0.1/(4+AR[z])**0.8))
if z <= 5: # line 33 #
z +=1
else :
break
n+=1
OUTPUT:
File "<ipython-input-49-d7d52927efb2>", line 33
if z <= 5:
^
SyntaxError: invalid syntax
This is a code which should tell me whether my aircraft will takeoff or not (on the input of a weight)
I cannot seem to understand the reason why is this syntax invalid ?
There are several errors in the code you provided. I tried to clean it up as best as I could. The following does not cause an error by default. This does not mean that the code does what it is supposed to do. You should still check that.
Your lists like CL and CD do not contain enough elements for most cases which will cause IndexError: list index out of range. You should extend those lists or use a different kind of logic to make sure this does not happen.
W = int(input('Enter weight:'))
b = [1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0]
AR = [1, 2, 3, 4, 5]
T = [
50.99238, 50.05062, 49.07943, 48.05919, 47.00952, 45.92061, 44.79246,
43.62507, 42.42825, 41.18238, 39.90708, 38.60235, 37.24857, 35.86536,
34.4331, 32.97141, 31.48029, 29.94012, 28.37052, 26.76168, 25.1136
]
CL = [1.0]
CD = [0.5]
clmax = 2
n = 0
z = 0
while b[n] < 2.1:
while AR[z] < 5.1:
cl = CL[n]
cd = CD[z]
s = ((b[n]*b[n])/AR[z])
V = ((2*W*9.81)/(1.2*s*clmax) ** 0.5)*1.1
vlof = V/1.41
Vlof = round(vlof)
D = 0.5*cd*1.2*Vlof*Vlof*s
L = 0.5*cl*1.2*Vlof*Vlof*s
# O.O5 -> 0.05*: you used the letter 'O' instead of '0' (zero). also
# you always have to use * if you want to multiply something. you
# cannot leave it out.
a = (9.81/W)*(T[Vlof]-D-0.05*(W-L))
Sg = (V*V)/(2*a)
if Sg <= 30:
print('IT WILL TAKEOFF')
else:
print('It will NOT takeoff')
# t/c -> t_c: you cannot use special characters when defining
# variables. best stick to lower- and upper-case letters,
# the underscore and numbers.
t_c = int(input('t/c ratio is:'))
l = int(input('Taper ratio is:'))
# a whole lot of closing parentheses and '*' were missing here. also
# cleaned up the formatting
f = 0.005*(1+1.5*((l-0.6)**2))
e = (
1 / (
(1+0.12*V*V*0.003*0.003)*(
1 + (
0.142+(f*AR[z]*(10*t_c)**0.33)
+ (0.1/(4+AR[z])**0.8)
)
)
)
)
# in Python, space has meaning. it determines which part of the code
# is executed at which level in the routine. you cannot chose it
# arbitrarily.
if z <= 5:
z += 1
else:
break
n += 1

How do I plot a vertical line with different colors, based on values in a database?

I am trying to plot a vertical line which represents depth. On different depths different types of soil are present and I would like to indicate these with different colors.
I have received data which is stored in a class. Based on a friction number I want to color the vertical line in three different colors. However, I don't know how I can achieve this.
The data is stored in ds1 (I have many different files (ds2, ds3, .. ds29) so making this work is convenient for me). ds1.depth calls the depth array, ds1.frictionnumber the friction number etc.
Due to the large amount of data and soil changes I don't know how to do this. It would be nice if something like below would work but I cannot get my head around it.
UPDATE: I found some code here -> http://abhay.harpale.net/blog/python/how-to-plot-multicolored-lines-in-matplotlib/
I adjusted my code and I get quite reasonable results, however something still goes wrong. In my data I've got 4 NaN values at the end (friction did not get measured). In the image below this should be from the horizontal line down, however that's not the case. How can I solve this, or what is going wrong?
UPDATE 2: The height of the line apparantly also scales with linewidth. Now I only need to find another way of plotting a wider line. Any suggestions are welcome.
def find_contiguous_colors(colors):
# finds the continuous segments of colors and returns those segments
segs = []
curr_seg = []
prev_color = ''
for c in colors:
if c == prev_color or prev_color == '':
curr_seg.append(c)
else:
segs.append(curr_seg)
curr_seg = []
curr_seg.append(c)
prev_color = c
segs.append(curr_seg) # the final one
return segs
def plot_multicolored_lines(x,y,colors):
segments = find_contiguous_colors(colors)
plt.figure(figsize=(12,8))
start= 0
for seg in segments:
end = start + len(seg)
l, = plt.gca().plot(x[start:end],y[start:end],lw=50,c=seg[0])
start = end
plt.axhline(-5.8988)
plt.axis('equal')
x = np.full(len(ds1.depth), 1)
y = ds1.depth
# color segments
colors = ['red']*len(ds1.depth)
for i in range(len(ds1.depth)):
if 0 < ds1.wrijvingsgetal[i] <= 1:
colors[i] = 'blue'
elif 1 < ds1.wrijvingsgetal[i] <= 2:
colors[i] = 'green'
elif ds1.wrijvingsgetal[i] > 2:
colors[i] = 'yellow'
else:
colors[i] = 'magenta'
Vertical soil profile
It's not efficient at all but I get the results I want. If someone knows how I could fix this by using stacked bargraph that is appreciated (for some reason I can't get it to work). My fix is presented below:
ds1 = read_gef(filepath)
def find_contiguous_colors(colors):
# finds the continuous segments of colors and returns those segments
segs = []
curr_seg = []
prev_color = ''
for c in colors:
if c == prev_color or prev_color == '':
curr_seg.append(c)
else:
segs.append(curr_seg)
curr_seg = []
curr_seg.append(c)
prev_color = c
segs.append(curr_seg)
return segs
def plot_multicolored_lines(x, y, colors):
segments = find_contiguous_colors(colors)
plt.figure(figsize=(12,8))
start= 0
for seg in segments:
end = start + len(seg)
l, = plt.gca().plot(x[start:end], y[start:end], lw=2, c=seg[0])
start = end
#plt.axhline(-5.8988, -1, 1)
x = np.full((len(ds1.depth), 2), 0)
y = np.array(ds1.depth)
# color segments
colors = ['red']*len(ds1.depth)
handle = [0] * 3
for i in range(len(ds1.depth)):
if 0 < ds1.wrijvingsgetal[i] <= 2:
colors[i] = 'yellow'
sandplt = plt.axhline(y[i], color=colors[i])
# elif 1 < ds1.wrijvingsgetal[i] <= 2:
# colors[i] = 'green'
# peatplt = plt.axhline(y[i], color=colors[i])
elif ds1.wrijvingsgetal[i] > 2:
colors[i] = 'green'
clayplt = plt.axhline(y[i], color=colors[i])
else:
colors[i] = 'magenta'
nanplt = plt.axhline(y[i], color=colors[i])
ratioxl = 1/5
plt.xlim(0, ratioxl*(ds1.depth[-1]-ds1.depth[0]))
plt.axis('scaled')
plt.ylabel('Depth w.r.t. groundlevel [m]')
plt.title('Vertical soil profile ' + str(Path(filepath).stem))
plt.tick_params(
axis='x', # changes apply to the x-axis
which='both', # both major and minor ticks are affected
bottom=False, # ticks along the bottom edge are off
top=False, # ticks along the top edge are off
labelbottom=False) # labels along the bottom edge are off
plt.legend(handles = (sandplt, clayplt, nanplt), labels=['Sand', 'Clay', 'Nan'], loc=[1.01, 0.78])
plt.savefig(os.path.join(wd, '..', '03data', '20190711-Wiertsema', 'VN72650-1_GEF', 'afbeeldingen') + '\VSP_' + str(Path(filepath).stem))
plt.show()

I am having a Quick Sort error with infinite re cursion

I am having problems with my quicksort function constantly re cursing the best of three function. I dont know why it is doing that and i need help. I am trying to practice this for my coding class next semester and this is one of the assignments from last year that my friend had and im lost when it comes to this error
This is my quicksort function:
def quick_sort ( alist, function ):
if len(alist) <= 1:
return alist + []
pivot, index = function(alist)
#print("Pivot:",pivot)
left = []
right = []
for value in range(len(alist)):
if value == index:
continue
if alist[value] <= pivot:
left.append(alist[value])
else:
right.append(alist[value])
print("left:", left)
print("right:", right)
sortedleft = quick_sort( left, function )
print("sortedleft", sortedleft)
sortedright = quick_sort( right, function )
print("sortedright", sortedright)
completeList = sortedleft + [pivot] + sortedright
return completeList
#main
alist = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
x = quick_sort(alist, best_of_three)
print(x)
this is my best of three function:
def best_of_three( bNlist, nine = False ):
rightindex = 2
middleindex = 1
if nine == False:
left = blist[0]
rightindex = int(len(blist) - 1)
rightvalue = int(blist[rightindex])
middleindex = int((len(blist) - 1)/2)
middlevalue = int(blist[middleindex])
bNlist.append(left)
bNlist.append(middlevalue)
bNlist.append(rightvalue)
BN = bNlist
print("Values:",BN)
left = bNlist[0]
middle = bNlist[1]
right = bNlist[2]
if left <= middle <= right:
return middle , middleindex
elif left >= middle >= right:
return middle, middleindex
elif middle <= right <= left:
return right, rightindex
elif middle >= right >= left:
return right, rightindex
else:
return left, 0
#main
bNlist = []
print('Best of Three')
blist = [54,26,93,17,77,31,44,55]
print("")
print( "List: [54,26,93,17,77,31,44,55]" )
x, index = best_of_three(bNlist)
print("Pivot: ",x)
print("----------------------------")
i really dont know why it keeps infinitely re cursing,
There is also a third function called ninther
def ninther( bNlist ):
stepsize = int(len(blist) / 9)
left = 0
middle = left + 2
right = left + 2 * stepsize
blist[left]
blist[middle]
blist[right]
leftvalue = blist[left]
rightvalue = blist[right]
middlevalue = blist[middle]
left2 = right + stepsize
middle2 = left2 + 2
right2 = left2 + 2 * stepsize
blist[left2]
blist[middle2]
blist[right2]
left2value = blist[left2]
middle2value = blist[middle2]
right2value = blist[right2]
left3 = right2 + stepsize
middle3 = left3 + 2
right3 = left3 + 2 * stepsize
blist[left3]
blist[middle3]
blist[right3]
left3value = blist[left3]
middle3value = blist[middle3]
right3value = blist[right3]
bN3list = []
bN2list = []
bNlist = []
bNlist.append(leftvalue)
bNlist.append(middlevalue)
bNlist.append(rightvalue)
bN2list.append(left2value)
bN2list.append(middle2value)
bN2list.append(right2value)
bN3list.append(left3value)
bN3list.append(middle3value)
bN3list.append(right3value)
BN3 = bN3list
BN2 = bN2list
BN = bNlist
print("Ninter ")
print("Group 1:", BN)
print("Group 2:", BN2)
print("Group 3:", BN3)
x = best_of_three(bNlist, True)[0]
c = best_of_three(bN2list, True)[0]
d = best_of_three(bN3list, True)[0]
print("Median 1:", x)
print("Median 2:", c)
print("Median 3:", d)
bN4list = [x,c,d]
print("All Medians:", bN4list)
z = best_of_three(bN4list, True)
return z[0], z[1]
#main
blist = [2, 6, 9, 7, 13, 4, 3, 5, 11, 1, 20, 12, 8, 10, 32, 16, 14, 17, 21, 46]
Y = ninther(blist)
print("Pivot", Y)
print("----------------------------")
i have looked everywhere in it and i cant figure out where the problem is when calling best of three
Summary: The main error causing infinite recursion is that you don't deal with the case where best_of_three receives a length 2 list. A secondary error is that best_of_three modifies the list you send to it. If I correct these two errors, as below, your code works.
The details: best_of_three([1, 2]) returns (2, 3), implying a pivot value of 2 at the third index, which is wrong. This would give a left list of [1, 2], which then causes exactly the same behavior at the next recursive quick_sort(left, function) call.
More generally, the problem is that the very idea of choosing the best index out of three possible values is impossible for a length 2 list, and you haven't chosen how to deal with that special case.
If I add this special case code to best_of_three, it deals with the length 2 case:
if len(bNlist) == 2:
return bNlist[1], 1
The function best_of_three also modifies bNlist. I have no idea why you have the lines of the form bNlist.append(left) in that function.
L = [15, 17, 17, 17, 17, 17, 17]
best_of_three(L)
print(L) # prints [15, 17, 17, 17, 17, 17, 17, 54, 17, 55]
I removed the append lines, since having best_of_three modify bNlist is unlikely to be what you want, and I have no idea why those lines are there. However, you should ask yourself why they are there to begin with. There might be some reason I don't know about. When I do that, there are a couple of quantities you compute that are never used, so I remove the lines that compute those also.
Then I notice you have the code
rightindex = 2
middleindex = 1
if nine == False:
rightindex = int(len(blist) - 1)
middleindex = int((len(blist) - 1)/2)
left = bNlist[0]
middle = bNlist[1]
right = bNlist[2]
This doesn't seem to make any sense, since you set rightindex and middleindex to other values, but then you still access values using the old indices (2 and 1 respectively). So I removed the if nine == False block. Again, ask yourself why you had this code to begin with, maybe there's some other way you should modify this to account for something I don't know about.
The result is the following for best_of_three:
def best_of_three(bNlist):
print(bNlist)
if len(bNlist) == 2:
return bNlist[1], 1
rightindex = 2
middleindex = 1
left = bNlist[0]
middle = bNlist[1]
right = bNlist[2]
if left <= middle <= right:
return middle , middleindex
elif left >= middle >= right:
return middle, middleindex
elif middle <= right <= left:
return right, rightindex
elif middle >= right >= left:
return right, rightindex
else:
return left, 0
If I use this, your code does not recurse infinitely, and it sorts.
I don't know why you mentioned ninther at all, since it seems to have nothing to do with your question. You should probably edit it to remove that code.

Selection sort not working with certain inputs... (or not displaying it correctly)

I wrote a function that takes two lists, Fahrenheit values and Celsius Values. I used a selection sort method that should sort the values from least to greatest. The possible Fahr Values are between and including -150 and 350 (I wrote a function to make sure input is within those numbers). When I type the following inputs: (30, 60, 10, -523235, -22, 30) it disregards the -523235 as it should but the output is: (10, 30, 60, -22, 30) which is not correct. It sorts only the first 3 numbers but once a negative is typed it doesn't sort that... I'm confused.
(The celsius values were generated by another function I wrote to convert the Fahr values to Cels values but that doesn't matter for this question)
def selection_sort_Fahr_Cels(temp_values_Fahr, temp_values_Cels):
for i in range(0, len(temp_values_Fahr)):
minIndex = i
for val in range(i+1, len(temp_values_Fahr)):
if temp_values_Fahr[val] < temp_values_Fahr[i]:
minIndex = val
if minIndex != i:
temp_values_Fahr[i], temp_values_Fahr[minIndex] = temp_values_Fahr[minIndex], temp_values_Fahr[i]
for i in range(0, len(temp_values_Cels)):
minIndex = i
for val in range(i+1, len(temp_values_Cels)):
if temp_values_Cels[val] < temp_values_Cels[i]:
minIndex = val
if minIndex != i:
temp_values_Cels[i], temp_values_Cels[minIndex] = temp_values_Cels[minIndex], temp_values_Cels[i]
print(" ", " Fahr "," ", " Cels ")
print(" ", "======="," ", "=======")
for i in range(len(temp_values_Fahr)):
print(" ","{0: 6}{1:14.1f}".format(temp_values_Fahr[i], temp_values_Cels[i]))
print(" ", "======="," ", "=======")
The entire program is over 100 lines, I can post a link to the entire program if needed.
Update: I can not use any library functions as to sort.
you don't really want to use all that complicated code to remove illegal values and sort them. There's a more pythonic way (I only did the Fahr values):
def selection_sort_Fahr_Cels(temp_values_Fahr, temp_values_Cels):
temp_values_Fahr[:] = sorted(filter(lambda x: x < 350 and x >= -150, temp_values_Fahr))
farh=[30, 60, 10, -523235, -22, 30]
selection_sort_Fahr_Cels(farh,[])
print(farh)
result (list is modified in-place):
[-22, 10, 30, 30, 60]
the code is using filter method using your criteria, and the result is passed to the sorted method that takes an iterable and creates a list out of it.
Not to mention that python sorted method is way more efficient than bubble sort.
def selectionsort( aList ):
for i in range( len( aList ) ):
least = i
for k in range( i + 1 , len( aList ) ):
if aList[k] < aList[least]:
least = k
swap( aList, least, i )
print(aList)
def swap( A, x, y ):
tmp = A[x]
A[x] = A[y]
A[y] = tmp
selectionsort(aList)
I found a better selection sort method. I noticed that before, I didn't have any swap method going on.

Resources