Matplotlib Errorbar Caps Missing - python

I'm attempting to create a scatter plot with errorbars in matplotlib. The following is an example of what my code looks like:
import matplotlib.pyplot as plt
import numpy as np
import random
x = np.linspace(1,2,10)
y = np.linspace(2,3,10)
err = [random.uniform(0,1) for i in range(10)]
plt.errorbar(x, y,
yerr=err,
marker='o',
color='k',
ecolor='k',
markerfacecolor='g',
label="series 2",
capsize=5,
linestyle='None')
plt.show()
The problem is the plot which is output contains no caps at all!
For what it's worth, I'm on Ubuntu 13.04, Python 2.7.5 |Anaconda 1.6.1 (64-bit)|, and Matplotlib 1.2.1.
Could this be a hidden rcparam that needs to be overwritten?

What worked for me was adding this (as per: How to set the line width of error bar caps, in matplotlib):
(_, caps, _) = plt.errorbar(x,y, yerr=err, capsize=20, elinewidth=3)
for cap in caps:
cap.set_color('red')
cap.set_markeredgewidth(10)

Slight simplification of astromax's answer:
plt.errorbar(x,y, yerr=err, capsize=20, elinewidth=3, markeredgewidth=10)
It seems that somehow markeredgewidth is defaulting to 0 sometimes.

It has to do with the rcParams in matplotlib. To solve it, add the following lines at the beginning of your script:
import matplotlib
matplotlib.rcParams.update({'errorbar.capsize': 2})
It also works with plt.bar().

Related

seaborn not coloring bars in barplot

I have started working on my thesis and I already have a problem.
I am trying to do a bar plot of ca. 250 bars, but it seems like that seaborn is not showing colors for most of the bars. I thought it could cycle through the palette - but it just shows them white. If I take a smaller sample (up to 99 I think), every bar is colored.
Even having one single color (not a palette), shows white bars.
Here is the code and the graph:
Can someone help me with this? Thank you!
I think that this problem arises because, by default in seaborn, the bars in a barplot are outlined with a thin white boundary line. When the bars themselves are very thin this white boundary is the only thing that you see. Try changing the plot command to:
g = sb.barplot(x = x, y = y, palette = sb.color_palette("RdBu", n_colors=7), lw=0.)
The lw=0. removes the boundary line and you should then see the bar colours.
Here's a piece of code to test the palettes of seaborn:
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sb
print("Seaborn version : {0}".format(sb.__version__))
# Seaborn version : 0.10.0
print("Matplotlib version : {0}".format(matplotlib.__version__))
# Matplotlib version : 3.1.3
Just to let you know it worked with these versions
# simple color test without palette
n = 1000
x = np.arange(1,n+1,1)
y = np.random.randint(-100,100,n)*np.random.random(n)
sb.barplot(x,y)
plt.xticks([])
plt.show()
# with your color choices
plt.figure(figsize=(20,20))
sb.barplot(x,y, palette=sb.color_palette("RdBu",n_colors=7))
plt.xticks([])
plt.show()
So it seems to work with the arrays of my code.
Maybe:
Your data is not understood by seaborn (check you dataframe?)
You have a bugged version of seaborn or matplotlib (try pip install seaborn==0.10.0 and pip install matplotlib==3.1.3)
You can try another palette of color
Hope this helps!
EDIT:
Thanks to #ImportanceOfBeingErnest, I think I understood your problem. It cames from this style, just comment/uncomment to see the result
# sb.set_style("darkgrid")
Sadly, I did not find any kwargs option related to the darkgrid style to remove the bug... So I propose we recreate this style manually!
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.set_facecolor('whitesmoke')
# background color
ax.grid(color='white', linestyle='-', linewidth=1)
# the grid
sb.barplot(x,y,zorder=2, palette=sb.color_palette("RdBu",n_colors=7))
#zorder=2 to draw above the grid
plt.xticks([])
plt.show()
Try sns.reset_orig() before plotting.

Transforming Seaborn axis to log [duplicate]

I want to plot a graph with one logarithmic axis using matplotlib.
I've been reading the docs, but can't figure out the syntax. I know that it's probably something simple like 'scale=linear' in the plot arguments, but I can't seem to get it right
Sample program:
import pylab
import matplotlib.pyplot as plt
a = [pow(10, i) for i in range(10)]
fig = plt.figure()
ax = fig.add_subplot(2, 1, 1)
line, = ax.plot(a, color='blue', lw=2)
pylab.show()
You can use the Axes.set_yscale method. That allows you to change the scale after the Axes object is created. That would also allow you to build a control to let the user pick the scale if you needed to.
The relevant line to add is:
ax.set_yscale('log')
You can use 'linear' to switch back to a linear scale. Here's what your code would look like:
import pylab
import matplotlib.pyplot as plt
a = [pow(10, i) for i in range(10)]
fig = plt.figure()
ax = fig.add_subplot(2, 1, 1)
line, = ax.plot(a, color='blue', lw=2)
ax.set_yscale('log')
pylab.show()
First of all, it's not very tidy to mix pylab and pyplot code. What's more, pyplot style is preferred over using pylab.
Here is a slightly cleaned up code, using only pyplot functions:
from matplotlib import pyplot
a = [ pow(10,i) for i in range(10) ]
pyplot.subplot(2,1,1)
pyplot.plot(a, color='blue', lw=2)
pyplot.yscale('log')
pyplot.show()
The relevant function is pyplot.yscale(). If you use the object-oriented version, replace it by the method Axes.set_yscale(). Remember that you can also change the scale of X axis, using pyplot.xscale() (or Axes.set_xscale()).
Check my question What is the difference between ‘log’ and ‘symlog’? to see a few examples of the graph scales that matplotlib offers.
if you want to change the base of logarithm, just add:
plt.yscale('log',base=2)
Before Matplotlib 3.3, you would have to use basex/basey as the bases of log
You simply need to use semilogy instead of plot:
from pylab import *
import matplotlib.pyplot as pyplot
a = [ pow(10,i) for i in range(10) ]
fig = pyplot.figure()
ax = fig.add_subplot(2,1,1)
line, = ax.semilogy(a, color='blue', lw=2)
show()
I know this is slightly off-topic, since some comments mentioned the ax.set_yscale('log') to be "nicest" solution I thought a rebuttal could be due. I would not recommend using ax.set_yscale('log') for histograms and bar plots. In my version (0.99.1.1) i run into some rendering problems - not sure how general this issue is. However both bar and hist has optional arguments to set the y-scale to log, which work fine.
references:
http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.bar
http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.hist
So if you are simply using the unsophisticated API, like I often am (I use it in ipython a lot), then this is simply
yscale('log')
plot(...)
Hope this helps someone looking for a simple answer! :).

How to plot and display a graph in Python

I wrote the code to plot and display a simple graph in Python:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import interactive
interactive(True)
x = np.arange(0,5,0.1)
y = np.sin(x)
plt.plot(x,y)
plt.show
And all I got is a blank screen.
And when I remove the "interactive" thing it shows no error but diplays nothing.
How can I display the graph?
(P.S: I use Python 2.7)
Remove these lines, they are not for a simple graphic:
from matplotlib import interactive
interactive(True)
And you're missing the () in the plt.show()
plt.show()
There is a syntax error. Replace plt.show with plt.show()
Just a note for others for future reference the full code should also include plt.figure() with the interactive elements removed.
Here what I came up with.
import matplotlib.pyplot as plt
import numpy as np
plt.figure()
x = np.arange(0, 5, 0.1)
y = np.sin(x)
plt.plot(x, y)
plt.show()
But this may be a 3.5 problem I've not tried in 2.7
You can also plot graphs with pyformulas.
First pip install pyformulas, then
import pyformulas as pf
import numpy as np
x = np.linspace(-10,10,100)
y = x**2 + x*np.e**(np.cos(x)**2)
pf.plot(x, y)
Disclaimer: I'm the maintainer of pyformulas

MatPlotLib's ion() and draw() not working

I am trying to plot figures in real time using a for loop. I have the following simple code:
import matplotlib.pyplot as plt
plt.ion()
plt.figure()
for i in range(100):
plt.plot([i], [i], 'o')
plt.draw()
plt.pause(0.0001)
This code does not show the figure until it has finished computing, which I don't want. I want it to draw the figure after every loop. If I replace plt.draw() with plt.show, multiple figures are output in real time, but I want them all to appear in the same figure. Any ideas?
EDIT:
I downloaded PyCharm with Anaconda and everything works fine. I guess it's a problem with Spyder since I tried a few different versions of it without success. If anyone has any clue what is causing this problem in Spyder, let me know!
Adapted for your case from : Python realtime plotting
import matplotlib.pyplot as plt
import numpy as np
import time
fig = plt.figure()
ax = fig.add_subplot(111)
# some X and Y data
x = [0]
y = [0]
li, = ax.plot(x, y,'o')
# draw and show it
fig.canvas.draw()
plt.show(block=False)
# loop to update the data
for i in range(100):
try:
x.append(i)
y.append(i)
# set the new data
li.set_xdata(x)
li.set_ydata(y)
ax.relim()
ax.autoscale_view(True,True,True)
fig.canvas.draw()
time.sleep(0.01)
except KeyboardInterrupt:
plt.close('all')
break
This solution example has worked for me on multiple machines. Try adjusting plt.pause(...)
import matplotlib.pyplot as plt
import numpy as np
F = lambda x: np.sin(2*x)
plt.ion()
x = np.linspace(0, 1, 200)
plt.plot(x, F(x))
for i in range(100):
if 'ax' in globals(): ax.remove()
newx = np.random.choice(x, size = 10)
ax = plt.scatter(newx, F(newx))
plt.pause(0.05)
plt.ioff()
plt.show()
Hey I was having the same problem, I checked other questions and my issue was solved when I plugged a pause into my solution. Here's some example code that worked for me.
import matplotlib.pyplot as plt
import numpy as np
plt.ion()
x = np.arange(0, 4*np.pi, 0.1)
y = [np.sin(i) for i in x]
plt.plot(x, y, 'g-', linewidth=1.5, markersize=4)
plt.pause(0.0001)
plt.plot(x, [i**2 for i in y], 'g-', linewidth=1.5, markersize=4)
plt.pause(0.0001)
plt.plot(x, [i**2*i+0.25 for i in y], 'r-', linewidth=1.5, markersize=4)
plt.pause(0.0001)
The solution was posted here:
Matplotlib ion() and subprocesses
The problem - and the solution - is highly dependent on the plot.draw() function within the Python environment and back end, and may even vary in different product releases. It manifests itself in different ways depending on the environment. The problem shows up in many places on stackoverflow with some solutions working for some people and not for others.
The gold standard on my Windows laptop is running the Python from the command line - no IDE, just plain vanilla Python3. draw() as shown in the example always works fine there.
If I try it in Jupyter notebook on the same machine, no amount of draw(), plot.pause(), plot.show(), or any other suggestion works. I tried %matplotlib with notebook, widget and ipympl. Nothing gets drawn until complete end of cell code execution.
Some other sources on stackoverflow suggested using figure.canvas.flush_events(). I had some success with that and investigated further.
The best solution turned out to be to run the draw() at the figure.canvas level instead of the axes or plot level.
You can get the figure by creating your plot with command:
fig, graph, = plt.subplots()
or, if you've already created the plot, as in the code at the top of the ticket, put the following outside the loop:
fig = plt.gcf() #get current figure
Inside the loop, instead of plt.draw(), use
fig.canvas.draw()
It's proven reliable in my Jupyter Notebook environment even when running multiple axes/plots across multiple figures. I can drop in sleep() statements and everything appears when expected.
Your mileage may vary.

What is the currently correct way to dynamically update plots in Jupyter/iPython?

In the answers to how to dynamically update a plot in a loop in ipython notebook (within one cell), an example is given of how to dynamically update a plot inside a Jupyter notebook within a Python loop. However, this works by destroying and re-creating the plot on every iteration, and a comment in one of the threads notes that this situation can be improved by using the new-ish %matplotlib nbagg magic, which provides an interactive figure embedded in the notebook, rather than a static image.
However, this wonderful new nbagg feature seems to be completely undocumented as far as I can tell, and I'm unable to find an example of how to use it to dynamically update a plot. Thus my question is, how does one efficiently update an existing plot in a Jupyter/Python notebook, using the nbagg backend? Since dynamically updating plots in matplotlib is a tricky issue in general, a simple working example would be an enormous help. A pointer to any documentation on the topic would also be extremely helpful.
To be clear what I'm asking for: what I want to do is to run some simulation code for a few iterations, then draw a plot of its current state, then run it for a few more iterations, then update the plot to reflect the current state, and so on. So the idea is to draw a plot and then, without any interaction from the user, update the data in the plot without destroying and re-creating the whole thing.
Here is some slightly modified code from the answer to the linked question above, which achieves this by re-drawing the whole figure every time. I want to achieve the same result, but more efficiently using nbagg.
%matplotlib inline
import time
import pylab as pl
from IPython import display
for i in range(10):
pl.clf()
pl.plot(pl.randn(100))
display.display(pl.gcf())
display.clear_output(wait=True)
time.sleep(1.0)
Here is an example that updates a plot in a loop. It updates the data in the figure and does not redraw the whole figure every time. It does block execution, though if you're interested in running a finite set of simulations and saving the results somewhere, it may not be a problem for you.
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
import time
def pltsin(ax, colors=['b']):
x = np.linspace(0,1,100)
if ax.lines:
for line in ax.lines:
line.set_xdata(x)
y = np.random.random(size=(100,1))
line.set_ydata(y)
else:
for color in colors:
y = np.random.random(size=(100,1))
ax.plot(x, y, color)
fig.canvas.draw()
fig,ax = plt.subplots(1,1)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_xlim(0,1)
ax.set_ylim(0,1)
for f in range(5):
pltsin(ax, ['b', 'r'])
time.sleep(1)
I put this up on nbviewer here.
There is an IPython Widget version of nbagg that is currently a work in progress at the Matplotlib repository. When that is available, that will probably be the best way to use nbagg.
EDIT: updated to show multiple plots
I'm using jupyter-lab and this works for me (adapt it to your case):
from IPython.display import clear_output
from matplotlib import pyplot as plt
import numpy as np
import collections
%matplotlib inline
def live_plot(data_dict, figsize=(7,5), title=''):
clear_output(wait=True)
plt.figure(figsize=figsize)
for label,data in data_dict.items():
plt.plot(data, label=label)
plt.title(title)
plt.grid(True)
plt.xlabel('epoch')
plt.legend(loc='center left') # the plot evolves to the right
plt.show();
Then in a loop you populate a dictionary and you pass it to live_plot():
data = collections.defaultdict(list)
for i in range(100):
data['foo'].append(np.random.random())
data['bar'].append(np.random.random())
data['baz'].append(np.random.random())
live_plot(data)
make sure you have a few cells below the plot, otherwise the view snaps in place each time the plot is redrawn.
If you don't want to clear all outputs, you can use display_id=True to obtain a handle and use .update() on it:
import numpy as np
import matplotlib.pyplot as plt
import time
from IPython import display
def pltsin(ax, *,hdisplay, colors=['b']):
x = np.linspace(0,1,100)
if ax.lines:
for line in ax.lines:
line.set_xdata(x)
y = np.random.random(size=(100,1))
line.set_ydata(y)
else:
for color in colors:
y = np.random.random(size=(100,1))
ax.plot(x, y, color)
hdisplay.update(fig)
fig,ax = plt.subplots(1,1)
hdisplay = display.display("", display_id=True)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_xlim(0,1)
ax.set_ylim(0,1)
for f in range(5):
pltsin(ax, colors=['b', 'r'], hdisplay=hdisplay)
time.sleep(1)
plt.close(fig)
(adapted from #pneumatics)
I've adapted #Ziofil answer and modified it to accept x,y as list and output a scatter plot plus a linear trend on the same plot.
from IPython.display import clear_output
from matplotlib import pyplot as plt
%matplotlib inline
def live_plot(x, y, figsize=(7,5), title=''):
clear_output(wait=True)
plt.figure(figsize=figsize)
plt.xlim(0, training_steps)
plt.ylim(0, 100)
x= [float(i) for i in x]
y= [float(i) for i in y]
if len(x) > 1:
plt.scatter(x,y, label='axis y', color='k')
m, b = np.polyfit(x, y, 1)
plt.plot(x, [x * m for x in x] + b)
plt.title(title)
plt.grid(True)
plt.xlabel('axis x')
plt.ylabel('axis y')
plt.show();
you just need to call live_plot(x, y) inside a loop.
here's how it looks:
The canvas.draw method of the figure dynamically updates its graphs, for the current figure:
from matplotlib import pyplot as plt
plt.gcf().canvas.draw()

Categories