plt.boxplot(data, vert = False) - adding one data point per boxplot - python 2.7, Matplotlib 1.5.3 - python-2.7

Have been trying to add one single point to my boxplots. I would like just to add a point as the black ones in the image below.
data_2 = [pd.read_csv(data).values for data in os.listdir(wd)]
bp = plt.boxplot(data_2, labels = labels, vert = False, showfliers = False)
plt.show()
Any ideas for how I should go with that? You can click here to see the pic

You can just plot individual points after the boxplot is finished, just give the appropiate coordinates:
import numpy as np
import matplotlib.pyplot as plt
data = np.array( [
np.random.normal( 0.19, 0.1, 100 ),
np.random.normal( 0.17, 0.1, 100 ),
np.random.normal( 0.11, 0.1, 100 ),
np.random.normal( 0.16, 0.1, 100 ),
np.random.normal( 0.15, 0.1, 100 ) ] ).T
labels = [ 'pred2012', 'pred2007', 'pred2002', 'pred1995', 'pred1988' ]
fig, ax = plt.subplots()
ax.boxplot( data, labels=labels, vert = False, showfliers = False)
ax.plot( -0.1, 4, marker='o' )
ax.plot( 0.3, 3, marker='*', markersize=20 )
plt.savefig( 'boxplot.png' )
plt.show()

Related

Question on Pyomo Transport/Shipping issue

I am learning pyomo and practicing an exercise about shipping problem with conditions below:
The shipment can either directly deliver from source cities to the destination or through a depot (source city -> depot -> destination)
The way of shipping will be selected based on least cost consumed
Every Depot has its own capacity limitation
I tried to use pyomo to solve this question, however, no solution can be figured out.
Please give me some advice and direction why the codes didnt work. Thank you!
import pyomo.environ as pyomo
import numpy as np
supply = dict({'Liverpool': 150000,
'Brighton': 200000})
through = dict({'Newcastle': 70000,
'Birmingham': 50000,
'London': 100000,
'Exeter': 40000,
'Liverpool': 150000,
'Brighton': 200000
})
demand = dict({'C1': 50000,
'C2': 10000,
'C3': 40000,
'C4': 35000,
'C5': 60000,
'C6': 20000})
cost = dict({
('Liverpool', 'Newcastle'): 0.5,
('Liverpool', 'Birmingham'): 0.5,
('Liverpool', 'London'): 1.0,
('Liverpool', 'Exeter'): 0.2,
('Liverpool', 'C1'): 1.0,
('Liverpool', 'C3'): 1.5,
('Liverpool', 'C4'): 2.0,
('Liverpool', 'C6'): 1.0,
('Brighton', 'Birmingham'): 0.3,
('Brighton', 'London'): 0.5,
('Brighton', 'Exeter'): 0.2,
('Brighton', 'C1'): 2.0,
('Newcastle', 'C2'): 1.5,
('Newcastle', 'C3'): 0.5,
('Newcastle', 'C5'): 1.5,
('Newcastle', 'C6'): 1.0,
('Birmingham', 'C1'): 1.0,
('Birmingham', 'C2'): 0.5,
('Birmingham', 'C3'): 0.5,
('Birmingham', 'C4'): 1.0,
('Birmingham', 'C5'): 0.5,
('London', 'C2'): 1.5,
('London', 'C3'): 2.0,
('London', 'C5'): 0.5,
('London', 'C6'): 1.5,
('Exeter', 'C3'): 0.2,
('Exeter', 'C4'): 1.5,
('Exeter', 'C5'): 0.5,
('Exeter', 'C6'): 1.5
})
cost_total = {}
for city_from in supply.keys():
for city_through in through.keys():
for city_to in demand.keys():
if city_from == city_through:
cost_total[(city_from , city_through , city_to)] = 0 + cost.get((city_through , city_to) , 9999)
else:
cost_total[(city_from , city_through , city_to)] = cost.get((city_from , city_through) , 9999) + cost.get((city_through , city_to) , 9999)
supplier = supply.keys()
througher = through.keys()
demander = demand.keys()
model = pyomo.ConcreteModel()
model.i = pyomo.Set(initialize = supplier , doc = 'City From')
model.j = pyomo.Set(initialize = througher , doc = 'City Through')
model.k = pyomo.Set(initialize = demander , doc = 'City To')
model.s = pyomo.Param(model.i , initialize=supply, doc='Supply by City')
model.t = pyomo.Param(model.j , initialize = through , doc = 'through / warehouse')
model.d = pyomo.Param(model.k , initialize=demand , doc='Demand by City')
model.cost = pyomo.Param(model.i , model.j , model.k , initialize=cost_total , doc = 'total cost')
model.x = pyomo.Var(model.i , model.j , model.k , bounds = (0 , None))
def supply_rule(model, i):
return sum(model.x[i,j,k] for j in model.j for k in model.k) <= model.s[i]
model.supply = pyomo.Constraint(model.i, rule=supply_rule, doc='Observe supply limit at plant i')
def demand_rule(model, k):
return sum(model.x[i,j,k] for i in model.i for j in model.j) == model.d[k]
model.demand = pyomo.Constraint(model.k, rule=demand_rule, doc='Satisfy demand at market j')
def depot_cont(model , j):
return sum(model.x[i , j , k] for i in model.i for k in model.k) <= model.t[j]
model.through_cont2 = pyomo.Constraint(model.j , rule = depot_cont)
def objective_rule(model):
return sum(model.cost[i,j,k]*model.x[i,j,k] for i in model.i for j in model.j for k in model.k)
model.objective = pyomo.Objective(rule=objective_rule, sense=pyomo.minimize, doc='Define objective function')
Your code (unmodified) appears to be working for me.
Realize there are a couple ways to set this up, which is a larger discussion... In your case you enumerated all possible routes, and snuck in a zero-cost option for the direct routes and added high cost for infeasible routes, which is fine. On a larger problem, or more complicated network, the standard way to approach this is as a network flow problem with flow-balance constraints at all the nodes (cities).
Anyhow, your question isn't too clear on what "isn't working". I added this to the end of your code:
solver = pyomo.SolverFactory('glpk')
result = solver.solve(model)
print(result)
for ijk in model.x.index_set():
if model.x[ijk]:
print(f'ship : {ijk} qty: {model.x[ijk].value}')
and it produced this result, which passes 1st level sanity check, but I didn't look at it too closely...
Problem:
- Name: unknown
Lower bound: 198500.0
Upper bound: 198500.0
Number of objectives: 1
Number of constraints: 15
Number of variables: 73
Number of nonzeros: 217
Sense: minimize
Solver:
- Status: ok
Termination condition: optimal
Statistics:
Branch and bound:
Number of bounded subproblems: 0
Number of created subproblems: 0
Error rc: 0
Time: 0.007380008697509766
Solution:
- number of solutions: 0
number of solutions displayed: 0
ship : ('Liverpool', 'Liverpool', 'C1') qty: 50000.0
ship : ('Liverpool', 'Liverpool', 'C6') qty: 20000.0
ship : ('Brighton', 'Birmingham', 'C2') qty: 10000.0
ship : ('Brighton', 'Birmingham', 'C4') qty: 35000.0
ship : ('Brighton', 'Birmingham', 'C5') qty: 5000.0
ship : ('Brighton', 'London', 'C5') qty: 55000.0
ship : ('Brighton', 'Exeter', 'C3') qty: 40000.0
[Finished in 579ms]

how to display the all intervals in colorbar using matplotlib

This is my code.I mentioned here 50 intervals,when i drag the slider then only i got 6 or 7 intervals,but i want to display the all my intervals in my colorbar. So can any one please guide me.Thank you in advance.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button
import matplotlib.colors
ax = plt.subplot(111)
plt.subplots_adjust(left=0.25, bottom=0.25)
img_data = np.random.rand(50,50)
c_max = 2
img = ax.imshow(img_data, interpolation='nearest')
cb = plt.colorbar(img)
axcolor = 'lightgoldenrodyellow'
ax_cmax = plt.axes([0.25, 0.15, 0.65, 0.03])
s_cmax = Slider(ax_cmax, 'max', 0, 50, valfmt=c_max)
def update(val, s=None):
# _cmin = s_cmin.val
_cmax = s_cmax.val
img.set_clim(_cmax)
plt.draw()
s_cmax.on_changed(update)
plt.show()
The argument to Slider called valfmt should be a string which is used to format the slider value.
So if you wanted to display 2 decimal places to the float you would need to make c_max = "%1.2f". Note that if you want to keep the minimum value at 0 you need to set that too in img.set_clim(0, _cmax)
c_max = "%1.2f"
img = ax.imshow(img_data, interpolation='nearest')
cb = plt.colorbar(img)
axcolor = 'lightgoldenrodyellow'
ax_cmax = plt.axes([0.25, 0.15, 0.65, 0.03])
s_cmax = Slider(ax_cmax, 'max', 0, 50, valfmt=c_max)
def update(val, s=None):
# _cmin = s_cmin.val
_cmax = s_cmax.val
img.set_clim(0, _cmax)
plt.draw()
s_cmax.on_changed(update)
plt.show()

Arbitrary number of 3d points how to zip to get x,y,z for plotting

I'm trying to plot a figure in 3D given an arbitrary number of points
import numpy as np
p = [
np.array([ 0.0, 0.0, 0.0]),
np.array([10.0, 0.0,10.0]),
np.array([10.0,21.0,10.0]),
np.array([14.5,25.5,14.5]),
np.array([ 0.0,40.0, 0.0]),
np.array([36.0,40.0, 0.0])]
... up to p[14]
section1 = [4, 0,1,2,3,4]
section2 = [8,14,1,2,8]
I need to combine p[4],p[0],p[1],p[2],p[3],p[4] and zip them to get the X,Y,Z I need to plot the lines.
I've been reduced to:
X=[]
Y=[]
Z=[]
for i in range(len(section1)):
X.append(p[section1[i]][0])
Y.append(p[section1[i]][1])
Z.append(p[section1[i]][2])
Whenever I put the points in a list and zip it, I get a strange list of the original points.
What is the right way to do it?
Your p is a list of arrays:
In [566]: p = [
...: np.array([ 0.0, 0.0, 0.0]),
...: np.array([10.0, 0.0,10.0]),
...: np.array([10.0,21.0,10.0]),
...: np.array([14.5,25.5,14.5]),
...: np.array([ 0.0,40.0, 0.0]),
...: np.array([36.0,40.0, 0.0])]
In [567]: len(p)
Out[567]: 6
In [568]: section1 = [4, 0,1,2,3,4]
I can convert that into a 2d array with np.stack:
In [569]: arr = np.stack(p)
In [570]: arr.shape
Out[570]: (6, 3)
Then it's easy to select rows with the section1 list:
In [571]: arr[section1,:]
Out[571]:
array([[ 0. , 40. , 0. ],
[ 0. , 0. , 0. ],
[ 10. , 0. , 10. ],
[ 10. , 21. , 10. ],
[ 14.5, 25.5, 14.5],
[ 0. , 40. , 0. ]])
X = arr[section1,0] and so on. Though for plotting you might not need to separate out the columns.
Here is a way to do that:
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
p=np.random.rand(50,3)
section=[[21, 13, 2, 36, 20, 15,21],[7, 14, 19, 32,7]]
fig = plt.figure()
ax = fig.gca(projection='3d')
color=['red','blue']
for i in range(2):
x,y,z=p[section[i]].T
ax.plot(x,y,z,color[i])
plt.show()
For :

How to add a time control panel to a FuncAnimation from matplotlib

I am currently using matplotlib.animation.FuncAnimation() to display an animation of my work, on a figure.
It is working very well, and I understand the arguments I am using ( interval, time range , ...) However, I was wondering if there was a way to implement (maybe directly to the figure) a panel containing the animation, a scroll-bar or whatever, which allows me to :
Move forward or backwards quickly to the time zone of interest.
Show at what point of the animation I am ( 10%, then 20%,...).
Basically, is a way to control the animation in python on the figure like the way I would control it as a video file played by a video player?
If needed, this is what looks like the code for this animation :
def init():
im1.set_data(XYslice[0, :, :])
im2.set_data(XZslice[0, Nplans/2:, :])
return([im1, im2])
def animate(t):
im1.set_data(XYslice[t, :, :])
im2.set_data(XZslice[t, Nplans/2:, :])
return [im1, im2]
anim = animation.FuncAnimation(fig, animate, np.arange(Ntime), interval=200,
blit=True, init_func=init, repeat=True)
What you are talking about is a GUI. The simplest example uses the matplotlib inbuilt widgets:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.mlab import bivariate_normal
from matplotlib.widgets import Slider, Button
#Setup figure and data
fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.25)
delta = 0.5
t = np.arange(0.0, 100.0, 0.1)
x = np.arange(-3.0, 4.001, delta)
y = np.arange(-4.0, 3.001, delta)
X, Y = np.meshgrid(x, y)
Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
Z = (Z1 - Z2) * 5.
cmap = plt.cm.rainbow
im = ax.pcolormesh(X, Y, Z, cmap=cmap)
fig.colorbar(im)
axcolor = 'lightgoldenrodyellow'
axtime = plt.axes([0.25, 0.1, 0.65, 0.03], axisbg=axcolor)
stime = Slider(axtime, 'Time', 0.0, 100.0, valinit=50.0)
#Routines to reset and update sliding bar
def reset(event):
stime.reset()
def update(val):
time = stime.val/10.
Z = (Z1 - Z2) * time
im.set_array(Z.ravel())
fig.canvas.draw()
#Bind sliding bar and reset button
stime.on_changed(update)
resetax = plt.axes([0.8, 0.025, 0.1, 0.04])
button = Button(resetax, 'Reset', color=axcolor, hovercolor='0.975')
button.on_clicked(reset)
plt.show()
This should be a start. If you want it to look better (and add more functionality) then you need to go to a GUI framework like wxpython, check out this example.
An example which is more inline with your data-structure would go as follows:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.mlab import bivariate_normal
from matplotlib.widgets import Slider, Button
#Setup figure and data
fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.25)
delta = 0.5
t = np.linspace(0.0, 100.0, 256)
x = np.linspace(-4.0, 4.001, 512)
y = np.linspace(-4.0, 4.001, 512)
X, Y = np.meshgrid(x, y)
Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
XZslice = np.zeros((256,512,512))
for i in range(t.shape[0]):
XZslice[i,:,:] = (Z1 - Z2) * t[i]/10.
cmap = plt.cm.rainbow
im = ax.pcolormesh(XZslice[128,:,:], cmap=cmap)
fig.colorbar(im)
axcolor = 'lightgoldenrodyellow'
axtime = plt.axes([0.25, 0.1, 0.65, 0.03], axisbg=axcolor)
stime = Slider(axtime, 'Time', 0.0, 100.0, valinit=50.0)
#Routines to reset and update sliding bar
def reset(event):
stime.reset()
def update(val):
time = int(stime.val/100.* 256)
im.set_array(XZslice[time,:,:].ravel())
fig.canvas.draw()
#Bind sliding bar and reset button
stime.on_changed(update)
resetax = plt.axes([0.8, 0.025, 0.1, 0.04])
button = Button(resetax, 'Reset', color=axcolor, hovercolor='0.975')
button.on_clicked(reset)
plt.show()

What is subplot_adjust() doing to pyplot axes?

I am trying to plot several subplots in a pyplot figure, one of which has two subplots. I handle this by creating one extra pyplot.ax based on the location of the bottom one.
Now, a problem arise when I adjust axes 1 through 4 using fig.subplots_adjust(), in order to leave an extra space on the right for legend. On the picture below, you can see that although my two datasets are the same length, the bar plot stretches further to the right.
I would like to apply the same adjustment to ax5 as I do to the other four axes when using fig.subplot_adjust(), but I cannot figure out what this method is doing with the
matplotlib.axes.Axes instance.
Looking at the documentation, I could not find a method that suits my purpose:
http://matplotlib.org/api/axes_api.html#matplotlib.axes.Axes
So what is fig.subplot_adjust() doing to my axes? How can I reproduce this behavior so that ALL axes align?
import numpy as np
import matplotlib.pyplot as plt
import datetime
fig, ( ax1, ax2, ax3 , ax4) = plt.subplots( figsize=(18.0, 11.0) , nrows=4, ncols=1)
## some fake stand-alone data
days = 365 * 5
dates = [datetime.datetime(2000, 1, 1, 0, 0) + datetime.timedelta( day - 1) for day in range(days)]
data_series = np.random.rand( days )
data_series2 = [np.sin(x * 2 * np.pi / 365 ) + np.random.rand(1) * 0.1 for x in range( days ) ]
###### Plots made up temperatures
ax4.set_frame_on(False)
ax4.plot_date( dates , data_series2 , color="black", ls="solid", lw=2, ms=0 )
# Now on the same plot try to add som precipitation as a plot
ax5 = fig.add_axes(ax4.get_position() , frameon=True, zorder = -10.0)
ax5.bar( dates, data_series, edgecolor="blue", zorder = -10.0 )
ax5.xaxis_date()
# gets rid of bar-plot labels
ax5.set_xticks([]); ax5.set_yticks([])
fig.subplots_adjust(right=0.8) # <- Pandora's box
plt.show()
The problem here is that ax5 is not in a subplot.
fig.get_axes()
[<matplotlib.axes._subplots.AxesSubplot at 0x220175c0>,
<matplotlib.axes._subplots.AxesSubplot at 0x18d48240>,
<matplotlib.axes._subplots.AxesSubplot at 0x1c5f3630>,
<matplotlib.axes._subplots.AxesSubplot at 0x1a430710>,
<matplotlib.axes._axes.Axes at 0x1c4defd0>] # There is ax5 and it is not under _subplots
so when you do
fig.subplots_adjust(right=0.8)
you adjust the subplot and not the axe directly so you don't affect ax5.
An easy way to correct than is to adjust ax4 before calling ax5, so ax5 will have the same proportion than ax4.
By calling
fig.subplots_adjust(right=0.8)
before
ax5 = fig.add_axes(ax4.get_position() , frameon=True, zorder = -10.0)
you will get the proper output.
So your code just have to look like that;
import numpy as np
import matplotlib.pyplot as plt
import datetime
fig, ( ax1, ax2, ax3 , ax4) = plt.subplots( figsize=(18.0, 11.0) , nrows=4, ncols=1)
## some fake stand-alone data
days = 365 * 5
dates = [datetime.datetime(2000, 1, 1, 0, 0) + datetime.timedelta( day - 1) for day in range(days)]
data_series = np.random.rand( days )
data_series2 = [np.sin(x * 2 * np.pi / 365 ) + np.random.rand(1) * 0.1 for x in range( days ) ]
###### Plots made up temperatures
ax4.set_frame_on(False)
ax4.plot_date( dates , data_series2 , color="black", ls="solid", lw=2, ms=0 )
# I move the subplot_adjust here before you create ax5
fig.subplots_adjust(right=0.8)
# Now on the same plot try to add som precipitation as a plot
ax5 = fig.add_axes(ax4.get_position() , frameon=True, zorder = -10.0)
ax5.bar( dates, data_series, edgecolor="blue", zorder = -10.0 )
ax5.xaxis_date()
# gets rid of bar-plot labels
ax5.set_xticks([]); ax5.set_yticks([])
plt.show()