The hold argument appears in many plotting functions, for example plt.fill_between, plt.arrow, plt.axhline (for import matplotlib.pyplot as plt). I can't find any documentation on it, however. Docs seem to only state:
Additional kwargs: hold = [True|False] overrides default hold state
This is also a difficult keyword argument to google for...
It appears to be based on MATLAB's default plotting, which requires hold on to be called in order to add more than one plot on the same graph. The default behaviour for matplotlib appears to be for this to be true, consider
import numpy as np
import matplotlib.pyplot as plt
x=np.linspace(0,np.pi*2,1000)
plt.plot(x,np.sin(x),hold=True)
plt.plot(x,np.sin(x)**2,hold=True)
plt.show()
which plots both lines on the same graph. If hold is set to false, the next call to plot overwrite the previous. For example,
import numpy as np
import matplotlib.pyplot as plt
x=np.linspace(0,np.pi*2,1000)
plt.plot(x,np.sin(x),hold=True)
plt.plot(x,np.sin(x)**2,hold=False)
plt.show()
From the documentation:
When hold is True, subsequent plot commands will be added to the current axes. When hold is False, the current axes and figure will be cleared on the next plot command
The value of hold determines if future plots are drawn over the previous one(s), or if the figure is cleared before drawing.
Related
I want to write a module with a function to set default style parameters from a matplotlibrc file. A minimal example of the module style.py:
import matplotlib as mpl
def set_default():
mpl.rc_file('./matplotlibrc')
If I want to use the module in a jupyter notebook with inline plotting, the inline plot is not shown, when I call style.set_default() before having plotted anything before.
So If I call
%matplotlib inline
style.set_default()
plt.plot()
the output is an empty list and no plot is shown. If I call e.g.
plt.plot()
after enabling inline plotting and before calling the set_default function, the output of both plot calls is shown inline.
This even happens, when the matplotlibrc file is empty as it is in my minimal example.
Does anyone understand why this happens and has an idea how to solve this problem or another way how to set a default style in a module using a matplotlibrc file?
Here are also two images of both cases in a jupyter notebook:
inline broken
inline working
Extra question: Why is the second plot in the second case larger, when the loaded matplotlibrc is empty?
Short version: Use mpl.style.use instead of mpl.rc_file.
Long version:
You may print out the backend in use to see what is going on.
import matplotlib as mpl
def set_default():
mpl.rc_file('matplotlibrc.txt') # this is an empty file
import matplotlib.pyplot as plt
print mpl.get_backend()
# This prints u'TkAgg' (in my case) the default backend in use
# due to my rc Params
%matplotlib inline
print mpl.get_backend()
# This prints "module://ipykernel.pylab.backend_inline", because inline has been set
set_default()
print mpl.get_backend()
# This prints "agg", because this is the default backend reset by setting the empty rc file
plt.plot()
# Here, no plot is shown because agg (a non interactive backend) is used.
Until here no supprise.
Now the second case.
import matplotlib as mpl
def set_default():
mpl.rc_file('matplotlibrc.txt') # this is an empty file
import matplotlib.pyplot as plt
print mpl.get_backend()
# This prints u'TkAgg' (in my case) the default backend in use, same as above
%matplotlib inline
print mpl.get_backend()
# This prints "module://ipykernel.pylab.backend_inline", because inline has been set
plt.plot()
# This shows the inline plot, because the inline backend is active.
set_default()
print mpl.get_backend()
# This prints "agg", because this is the default backend reset by setting the new empty rc file
plt.plot()
# Here comes the supprise: Although "agg" is the backend, still, an inline plot is shown.
# This is due to the inline backend being the one registered in pyplot
# when doing the first plot. It cannot be changed afterwards.
The main point is, you may still change the backend, until the first plot is produced, not after.
The same argument goes for the figure size. The default matplotlib figure size is (6.4,4.8), while the one being set with the inline backend is (6.0,4.0). Also the figure dpi is different, it is 100 in the default rcParams, but 72. in the inline configuration. This makes the plot appear much smaller.
Now to the actual problem. I suppose the use of a stylesheet is meant here to set some styles for plots, not to change the backend. Hence you would rather only set the style from the rc file. This can be done in the usual way,using matplotlib.style.use
def set_default():
mpl.style.use('matplotlibrc.txt')
When this is used, it will not overwrite the backend in use, but only update those parameters, specified in the file itself.
I am creating a large array of subplots and I want to turn off axes for all the subplots.
Currently I am achieving this by
fig, ax = plt.subplots(7, len(clusters))
fig.subplots_adjust(wspace=0, top=1.0, bottom=0.5, left=0, right=1.0)
for x in ax.ravel():
x.axis("off")
but looping over the subplots to turn of the axes individually is ugly.
Is there a way to tell subplots to turn od axes at creation time
or some setting on Figure or pyplot that turns axes off globally.
pyplot.axis('off') turns off axes just on the last subplot.
I agree with #tcaswell that you should probably just use what you're already using. Another option to use it as a function is to use numpy.vectorize():
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(7, len(clusters))
np.vectorize(lambda ax:ax.axis('off'))(ax)
or, if you need to invoke it multiple times, by assigning the vectorized function to a variable:
axoff_fun = np.vectorize(lambda ax:ax.axis('off'))
# ... stuff here ...
fig, ax = plt.subplots(7, len(clusters))
axoff_fun(ax)
Again, note that this is the same thing that #tcaswell suggested, in a fancier setting (only slower, probably). And it's essentially the same thing you're using now.
However, if you insist on doing it some other way (i.e. you are a special kind of lazy), you can set matplotlib.rcParams once, and then every subsequent axes will automatically be off. There's probably an easier way to emulate axis('off'), but here's how I've succeeded:
import matplotlib as mpl
# before
mpl.pyplot.figure()
mpl.pyplot.plot([1,3,5],[4,6,5])
# kill axis in rcParams
mpl.rc('axes.spines',top=False,bottom=False,left=False,right=False);
mpl.rc('axes',facecolor=(1,1,1,0),edgecolor=(1,1,1,0));
mpl.rc(('xtick','ytick'),color=(1,1,1,0));
# after
mpl.pyplot.figure()
mpl.pyplot.plot([1,3,5],[4,6,5])
Result before/after:
Hopefully there aren't any surprises which I forgot to override, but that would become clear quite quickly in an actual application anyway.
How do pyplot functions such as show() and savefig() not require a "plot object" to work?
For example, the following code works, but somehow I expect to use a file handler or pass a "plot object" into plt.show() and plot.savefig("venn3.pdf").
from matplotlib import pyplot as plt
from matplotlib_venn import venn3, venn3_circles
# Subset sizes
s = (2,3,4,3,1,0.5,4)
v = venn3(subsets=s, set_labels=('A', 'B', 'C'))
# Subset labels
v.get_label_by_id('100').set_text('Abc')
v.get_label_by_id('010').set_text('aBc')
v.get_label_by_id('110').set_text('ABc')
v.get_label_by_id('001').set_text('Abc')
v.get_label_by_id('101').set_text('aBc')
v.get_label_by_id('011').set_text('ABc')
v.get_label_by_id('111').set_text('ABC')
# Subset colors
v.get_patch_by_id('100').set_color('c')
v.get_patch_by_id('010').set_color('#993333')
v.get_patch_by_id('110').set_color('blue')
# Subset alphas
v.get_patch_by_id('101').set_alpha(0.4)
v.get_patch_by_id('011').set_alpha(1.0)
v.get_patch_by_id('111').set_alpha(0.7)
# Border styles
c = venn3_circles(subsets=s, linestyle='solid')
c[0].set_ls('dotted') # Line style
c[1].set_ls('dashed')
c[2].set_lw(1.0) # Line width
plt.show() # For show() to work without using variable v seems counter-intuitive to me.
plt.savefig("venn3.pdf") # For savefig() to work without using variable v seems counter-intuitive to me.
2[]
matplotlib.pyplot is often called "statemachine". This means that the function it provides do certain things depending on the internal state of pyplot.
In your code, you have created a figure and this is stored as an object; pyplot knows it has one figure.
If you then call other commands, it is assumend that they apply to that one figure which has been created previously, like plt.savefig.
plt.show() would work on all previously created figures (all of them would be shown).
Pyplot uses a global variable to hold the figure object. All pyplot functions work with that variable(s). If you are working interactively, pyplot is perfectly fine since only you will modify that variable. If you are writing multi-threaded or multi-user code pyplot will not work, and you would have to use the layer benath it, which needs the figure object passed in (and is a terrible interface).
I plot a figure containing several curves using matplotlib and then try to convert it into bokeh:
import numpy as np
import matplotlib.pyplot as plt
from bokeh import mpl
from bokeh.plotting import show, output_file
num_plots = 6
colormap = plt.cm.gist_ncar
time = np.random.random_sample((300, 6))
s_strain = np.random.random_sample((300, 6))
def time_s_strain_bokeh(num_plots, colormap, time, s_strain):
plt.gca().set_color_cycle([colormap(i) for i in np.linspace(0, 0.9, num_plots)])
plt.figure(2)
for i in range(0, num_plots):
plt.plot(time[:,i], s_strain[:,i])
plt.grid(True)
# save it to bokeh
output_file('anywhere.html')
show(mpl.to_bokeh())
time_s_strain_bokeh(num_plots, colormap, time, s_strain)
it works fine. However, I want to have a semilogx plot. When I change plt.plot in the "for" loop into plt.semilogx, I have the following error:
UnboundLocalError: local variable 'laxis' referenced before assignment
What can I do to change the x-axis onto log scale?
I'm with the same issue! 1/2 of the solution is this (supose my data is in a Pandas dataframe called pd):
pd.plot(x='my_x_variable', y='my_y_variable)
p = mpl.to_bokeh()
p.x_mapper_type='log' # I found this property with p.properties_with_values()
show(p)
I edited this answare because I just found part 2/2 of the solution:
When I use just the code above, the plot is semilog (ok!), but the x axis is flipped (mirrored)!!!
The solution I found is explicitly redefine xlim:
p.x_range.start=0.007 # supose pd['my_x_variable'] starts at 0.007
p.x_range.end=0.17 # supose pd['my_x_variable'] ends at 0.17
With this my plot became identical with the matplotlib original plot. The final code looks like:
pd.plot(x='my_x_variable', y='my_y_variable)
p = mpl.to_bokeh()
p.x_mapper_type='log'
p.x_range.start= pd['my_x_variable'].iloc[1] # numpy start at 0, take care!
p.x_range.end= pd['my_x_variable'].iloc[-1]
show(p)
As of Bokeh 0.12, partial and incomplete MPL compatibility is provided by the third party mplexporter library, which now appears to be unmaintained. Full (or at least, much more complete) MPL compat support will not happen until the MPL team implements MEP 25. However, implementing MEP 25 is an MPL project task, and the timeline/schedule is entirely outside of the control of the Bokeh project.
The existing MPL compat based on mplexporter is provided "as-is" in case it is useful in the subset of simple situations that it currently works for. My suggestion is to use native Bokeh APIs directly for anything of even moderate complexity.
You can find an example of a semilog plot created using Bokeh APIs here:
http://docs.bokeh.org/en/latest/docs/user_guide/plotting.html#log-scale-axes
You can specify a color for plots, but Seaborn will mute the color a bit during plotting. Is there a way to turn off this behavior?
Example:
import matplotlib
import seaborn as sns
import numpy as np
# Create some data
np.random.seed(0)
x = np.random.randn(100)
# Set the Seaborn style
sns.set_style('white')
# Specify a color for plotting
current_palette = matplotlib.colors.hex2color('#86b92e')
# Make a plot
g = sns.distplot(x, color=current_palette)
# Show what the color should look like
sns.palplot(current_palette)
I have tried several ways of specifying the color and all available styles in Seaborn, but nothing has worked. I am using iPython notebook and Python 2.7.
It is not using a muted color, its using an alpha/transparency value as part of the default.
Two answers referencing ways to modify matplotlib object transparency:
https://stackoverflow.com/a/4708018
https://stackoverflow.com/a/24549558
seaborn.distplot allows you to pass different parameters for styling (*_kws). Each plot function has it's own parameters and are therefor prefixed by the name of the plot. Eg. histogram has hist_kws. [distplot Reference]
Because the histogram plot is located in matplotlib, we'd have to look at the keyword parameters we can pass. Like you already figured out, you can pass the 'alpha' keyword parameter to get rid of the transparancy of the lines. See reference for more arguments (kwargs section). [pyplot Reference]