I have a problem with creating 2 dimensional array - python-3.x

I defined a function that changes list (basically moves the last item to the start of list) and then i tried to make a 2d list with this fuction.
Here's some code:
prevRow = ["blue", "yellow", "red", "black", "white"]
def nextRow():
prevRow.insert((0, prevRow.pop()))
print(prevRow)
return prevRow
tablePreset = [["blue", "yellow", "red", "black", "white"], nextRow(), nextRow(), nextRow(), nextRow()]
print(tablePreset)
prevRow = ["blue", "yellow", "red", "black", "white"]
tablePreset = [["blue", "yellow", "red", "black", "white"]]
def nextRow():
prevRow.insert((0, prevRow.pop()))
print(prevRow)
return prevRow
for _ in range(4):
tablePreset.append(nextRow())
print(tablePreset)
in both cases i got the
['white', 'blue', 'yellow', 'red', 'black']
['black', 'white', 'blue', 'yellow', 'red']
['red', 'black', 'white', 'blue', 'yellow']
['yellow', 'red', 'black', 'white', 'blue']
[['blue', 'yellow', 'red', 'black', 'white'], ['yellow', 'red', 'black', 'white', 'blue'], ['yellow', 'red', 'black', 'white', 'blue'], ['yellow', 'red', 'black', 'white', 'blue'], ['yellow', 'red', 'black', 'white', 'blue']]
I don't know why but even though i called function 4 times, every return in the list is the same as the last value (print inside the function is for debugging purposes).
I'll be very greatfull if someone helps me :)

You need to make a copy of the list every time it's passed to the function nextRow (see code below). Some more information here (related topic).
prevRow = ["blue", "yellow", "red", "black", "white"]
tablePreset = [["blue", "yellow", "red", "black", "white"]]
def nextRow(prevRow):
prevRow_copy = prevRow.copy()
prevRow_copy.insert(0, prevRow_copy.pop())
return prevRow_copy
for _ in range(4):
prevRow = nextRow(prevRow)
tablePreset.append(prevRow)
print(tablePreset)
# >> out:
# [['blue', 'yellow', 'red', 'black', 'white'],
# ['white', 'blue', 'yellow', 'red', 'black'],
# ['black', 'white', 'blue', 'yellow', 'red'],
# ['red', 'black', 'white', 'blue', 'yellow'],
# ['yellow', 'red', 'black', 'white', 'blue']]
Another small example illustrating the importance of the copy:
a = []
b = [1,2,3]
a.append(b)
b.pop()
a.append(b)
b.pop()
a.append(b)
print(a)
# >> out:
# [[1], [1], [1]]
a = []
b = [1,2,3]
a.append(b.copy())
b.pop()
a.append(b.copy())
b.pop()
a.append(b.copy())
print(a)
# >> out:
# [[1, 2, 3], [1, 2], [1]]

Related

How to add vertical line to multiple subplots in plotly?

I have a Figure made up of 4 subplots, each subplot looks like this:
Data:Histogram({
'autobinx': False,
'histnorm': 'probability density',
'legendgroup': 'HOM_TP',
'marker': {'color': '#eb8909'},
'name': 'HOM_TP',
'opacity': 0.7,
'x': array([99., 99., 99., ..., 99., 99., 99.]),
'xaxis': 'x',
'xbins': {'end': 99.0, 'size': 0.0, 'start': 99.0},
'yaxis': 'y'
})
Layout({
'annotations': [{'showarrow': False,
'text': 'TEXT',
'x': 2.5,
'xanchor': 'left',
'xref': 'x',
'y': 1,
'yanchor': 'top',
'yref': 'y domain'}],
'shapes': [{'line': {'color': 'green', 'dash': 'dash', 'width': 3},
'type': 'line',
'x0': 2.5,
'x1': 2.5,
'xref': 'x',
'y0': 0,
'y1': 1,
'yref': 'y domain'}],
'sliders': [{'active': 10,
'currentvalue': {'prefix': 'Frequency: '},
'pad': {'t': 50},
'steps': [{'args': [{'visible': [True]}, {'title': 'Slider switched to step: 0'}], 'method': 'update'}]}],
'template': '...'
})
I can add each plot to the main Figure using add_trace(subplot.data) but this does not bring the layout info (sliders and vertical line). How can I add the layout to the subplots within the main figure?
Current code:
def make_tiled_figure(subfigs, metric):
'''
Take list of figures ( figure factory plot objects) to be combined into
tiled image. Return single figure object with tiled subplots.
'''
fig = make_subplots(rows=1, cols=4, subplot_titles=[
'SNP', 'INDEL', 'HET', 'HOM'])
# decide on position and add subfigures to plot
for i, subfig in enumerate(subfigs):
if subfig:
for trace in subfig.data:
fig.add_trace(trace, row=1, col=i+1)
fig.update_layout(subfig.layout)
# specify plot size and title
fig.update_layout(height=500, width=1800, title_text=metric)
return fig
My eventual goal is to have a vertical line that can slide across each subplot, controlled by the sliders (essentially by having multiple lines made visible/invisible by the slider position). If there is a better way of achieving this I am very open to suggestions.

merging and calculating sum in dictionaries

let_col= {'t': ['black', 'golden', 'silver'], 'f': ['blue', 'green'], 's': ['grey', 'yellow'], 'k': ['red', 'purple']}
col_pix = {'blue':150,'red':200,'green':160,'grey':240,'purple':210,'black':140,'yellow':120,'golden':130,'silver':200}
I would like to merge these two dictionaries as :
let_col_pixels = {'t': ['black':140, 'golden':130, 'silver':200],'f':[] ....}
Then I have to add total pixels for each letter. can someone please help me , I tried many things but still unable to do it. Thanks
I hope I understand your question right, this script will merge the dictionaries and adds key total_sum to each letter:
let_col= {'t': ['black', 'golden', 'silver'], 'f': ['blue', 'green'], 's': ['grey', 'yellow'], 'k': ['red', 'purple']}
col_pix = {'blue':150,'red':200,'green':160,'grey':240,'purple':210,'black':140,'yellow':120,'golden':130,'silver':200}
out = {k: dict(**v, total_sum=sum(v.values())) for k, v in {k:{vv: col_pix[vv] for vv in v} for k, v in let_col.items()}.items()}
from pprint import pprint
pprint(out)
Prints:
{'f': {'blue': 150, 'green': 160, 'total_sum': 310},
'k': {'purple': 210, 'red': 200, 'total_sum': 410},
's': {'grey': 240, 'total_sum': 360, 'yellow': 120},
't': {'black': 140, 'golden': 130, 'silver': 200, 'total_sum': 470}}

Optimization using pulp python

Trying to write an optimization code using pulp.
From the given dataset i want to 5 items which in sum maximize the value whereas having constraints as 2 items having color blue, 2 items having color yellow and a random item
But instead by using the attached code i am getting only 3 items, Please refer output section
Please suggest the changes needs to be done to the existing code
import pandas as pd
import pulp
import re
import sys
sys.setrecursionlimit(10000)
data = [['A', 'blue', 'circle', 0.454],
['B', 'yellow', 'square', 0.570],
['C', 'red', 'triangle', 0.789],
['D', 'red', 'circle', 0.718],
['E', 'red', 'square', 0.828],
['F', 'orange', 'square', 0.709],
['G', 'blue', 'circle', 0.696],
['H', 'orange', 'square', 0.285],
['I', 'orange', 'square', 0.698],
['J', 'orange', 'triangle', 0.861],
['K', 'blue', 'triangle', 0.658],
['L', 'yellow', 'circle', 0.819],
['M', 'blue', 'square', 0.352],
['N', 'orange', 'circle', 0.883],
['O', 'yellow', 'triangle', 0.755]]
df = pd.DataFrame(data, columns = ['item', 'color', 'shape', 'value'])
BlueMatch = lambda x: 1 if x=='blue' else 0
YellowMatch = lambda x: 1 if x=='yellow' else 0
RedMatch = lambda x: 1 if x=='red' else 0
OrangeMatch = lambda x: 1 if x=='orange' else 0
df['color'] = df['color'].astype(str)
df['isBlue'] = df.color.apply(BlueMatch)
df['isYellow'] = df.color.apply(YellowMatch)
df['isRed'] = df.color.apply(RedMatch)
df['isOrange'] = df.color.apply(OrangeMatch)
prob = pulp.LpProblem("complex_napsack", pulp.LpMaximize)
x = pulp.LpVariable.dicts( "x", indexs = df.index, lowBound=0, cat='Integer')
prob += pulp.lpSum([x[i]*df.value[i] for i in df.index ])
prob += pulp.lpSum([x[i]*df.isBlue[i] for i in df.index])==2
prob += pulp.lpSum([x[i]*df.isYellow[i] for i in df.index])==2
prob += pulp.lpSum([x[i] for i in df.index ])==10
prob.solve()
for v in prob.variables():
if v.varValue != 0.0:
mystring = re.search('([0-9]*$)', v.name)
print(v.name, "=", v.varValue)
ind = int(mystring.group(1))
print(df.item[ind])
output:
x_11 = 2.0
L
x_13 = 6.0
N
x_6 = 2.0
G
You just need to declare your variables as Binary instead of Integer, like so:
x = pulp.LpVariable.dicts("x", indexs=df.index, cat=pulp.LpBinary)

Boolean Operators are not working consistently. Prints "a" correctly, but prints "b" incorrectly [duplicate]

This question already has answers here:
How to test the membership of multiple values in a list
(12 answers)
Closed 4 years ago.
So, I want to write this program where I define a class, and the method within it takes a list of colours as an argument. The colours "red", "Red, "green" and "Green" should be replaced with "black", "Black", "white" and "White" (see the dictionary "self.colour_replacement" in the code-text).
If only one of the two colors red/green regardsless of capital letter, is in the list, the program should only return the list without changing it.
Example_1:
print(c.make_readable(['Green', 'Green', 'pink', 'green', 'yellow', 'green',
'green']))
should return:
['Green', 'Green', 'pink', 'green', 'yellow', 'green', 'green']
Example_2:
print(c.make_readable(['green', 'Green']))
should return:
['green', 'Green']
I think the problem has to do with my "or" and "and" statements in the line:
if ('red' and 'green') in colours or ('Red' and 'green') in colours or
('red' and 'Green') in colours or ('Red' and 'Green') in colours:
but I am not entirely sure.
class ColourChanger:
def __init__(self):
"""A dictionary that shows the
replacement colours."""
self.colour_replacement = {'Green' : 'White', 'red': 'black',
'green': 'white', 'Red' : 'Black'}
def make_readable(self, colours):
result = []
if ('red' and 'green') in colours or ('Red' and 'green') in colours or
('red' and 'Green') in colours or ('Red' and 'Green') in colours:
for col in colours:
if col in self.colour_replacement:
result.append(self.colour_replacement[col]) """Appends the
"result"-list with the replacement color instead of the color (col)."""
else:
result.append(col)
else:
return colours
return result
c = ColourChanger()
print(c.make_readable(['green', 'Green']))
print(c.make_readable(['Red', 'red']))
print(c.make_readable(['Red', 'Red', 'pink', 'red', 'yellow', 'red', 'red',
'Green']))
print(c.make_readable(['Green', 'Green', 'pink', 'green', 'yellow', 'green',
'green']))
Expected output:
['green', 'Green']
['Red', 'red']
['Black', 'Black', 'pink', 'black', 'yellow', 'black', 'black', 'White']
['Green', 'Green', 'pink', 'green', 'yellow', 'green', 'green']
Actual Output:
['white', 'White']
['Red', 'red']
['Black', 'Black', 'pink', 'black', 'yellow', 'black', 'black', 'White']
['White', 'White', 'pink', 'white', 'yellow', 'white', 'white']
Your condition is wrong, to fix it use
if ('red' in colours and 'green' in colours) or ( ...) .... :
but its not needed - as much is shared in the dupe.
You can avoid most of your ifs alltogether. There is very few benefit in checking first if something is in the list and then conditionally build the replacement to return it. You might sometimes omit building the replacement list which can be a benefit if your lists are huge but you will still have to iterate each list once to its full length to "see" this. You will also need to do this for all lists that would need to get a substitute list to be built - thouse would be traversed more then once - eating up all the "time" you saved for those that do not need replacements. For short(ish) lists its easier to simply build the replacement every time:
It is easier to build the "replace" on the first run through your data:
class ColourChanger:
def __init__(self):
# A dictionary that shows the replacement colours - only lowercase needed
self.colour_replacement = {'green' : 'white', 'red': 'black'}
def make_readable(self, colours):
result = []
# iterate all col's, append them if not in dict, else append the replacement
for col in colours:
replace = self.colour_replacement.get(col.lower(), col)
# adjust case-ness by string-splicing with uppercase where needed
if col[0].isupper() and replace[0].islower():
replace = replace[0].upper()+replace[1:]
result.append(replace)
return result
c = ColourChanger()
print(c.make_readable(['green', 'Green']))
print(c.make_readable(['Red', 'red']))
print(c.make_readable(['Red', 'Red', 'pink', 'red', 'yellow', 'red', 'red',
'Green']))
print(c.make_readable(['Green', 'Green', 'pink', 'green', 'yellow', 'green',
'green']))
Output:
['white', 'White']
['Black', 'black']
['Black', 'Black', 'pink', 'black', 'yellow', 'black', 'black', 'White']
['White', 'White', 'pink', 'white', 'yellow', 'white', 'white']
See Why dict.get(key) instead of dict[key]? for why using .get(key, default).

Python random choice from list

How do i choose to pick random choice from the list given below.
colours = ['red', 'blue', 'green', 'yellow', 'black', 'purple', 'Brown', 'Orange', 'violet', 'gray']
now pick 1 item from above 10 items list.
print
pick 2 items from remaining 9 items.
print
finally pick 3 items from remaining 7 items.
print
So final result will be like this
Brown
green and violet
red black and gray
A simple way would just be to delete the chosen values from the list. It is slightly simpler if you use sets:
In []:
colours = {'red', 'blue', 'green', 'yellow', 'black', 'purple',
'Brown', 'Orange', 'violet', 'gray'}
for n in [1, 2, 3]:
cs = random.sample(colours, k=n)
colours -= set(cs)
print(cs)
Out[]:
['Brown']
['Orange', 'red']
['purple', 'gray', 'blue']
colors = ['red', 'blue', 'green', 'yellow', 'black', 'purple','Brown', 'Orange', 'violet', 'gray']
for n in range(1,4):
select=np.random.choice(colors,n)
print(select)
colors=list(set(colors).difference(set(select)))
output:-['Brown']
['red' 'violet']
['yellow' 'Orange' 'black']
The method I use consist in shuffling your input vector take the selected number of elements you need.
import random
colours = ['red', 'blue', 'green', 'yellow', 'black', 'purple', 'Brown', 'Orange', 'violet', 'gray']
random.shuffle(colours)
for i in range(1, 4):
n, colours = colours[0:i], colours[i:]
print(n)

Resources