I am looking for a way to set a black border on the errorbars in my plot,
The following code:
ax.errorbar(x, y, yerr, fmt='o', label='label',color="#8da0cb",capthick=2, elinewidth=2,zorder=10)
produces:
I find it more aesthetically pleasing if there was a black border around the errorbar like there is on the marker.
Thanks for any help you can provide
Not a great solution, but you could get close by plotting the errorbars again behind your original ones, with a wider line and cap thinkness, and setting the colour of those ones to black. We can make use of the zorder kwarg to put them behind the others.
Heres a MWE:
import matplotlib.pyplot as plt
import numpy as np
# Fake data
x=np.arange(0,5,1)
y=np.ones(x.shape)
yerr = np.ones(x.shape)/4.
# Create figure
fig,ax = plt.subplots(1)
# Set some limits
ax.set_xlim(-1,5)
ax.set_ylim(-2,4)
# Plot errorbars with the line color you want
ax.errorbar(x,y,yerr, fmt='o',color='r',capthick=2,elinewidth=2,capsize=3,zorder=10)
# Plot black errorbars behind (lower zorder) with a wider line and cap thinkness
ax.errorbar(x,y,yerr, fmt='o',color='k',capthick=4,elinewidth=4,capsize=4,zorder=5)
plt.show()
Again, not a perfect solution, but at least it allows you to include it in the legend. This time, rather than plot the errorbars twice, we will use the matplotlib.patheffects module to add a Stroke to the errorbars.
errorbar returns several Line2D and LineCollection objects, so we need to apply the stroke to each of the relevant ones.
import matplotlib.patheffects as path_effects
e = ax.errorbar(x,y,yerr, fmt='o',color='r',capthick=2,elinewidth=2, label='path effects')
e[1][0].set_path_effects([path_effects.Stroke(linewidth=4, foreground='black'),
path_effects.Normal()])
e[1][1].set_path_effects([path_effects.Stroke(linewidth=4, foreground='black'),
path_effects.Normal()])
e[2][0].set_path_effects([path_effects.Stroke(linewidth=4, foreground='black'),
path_effects.Normal()])
ax.legend(loc=0)
As far as I can see from the information provided in the webpage of pyplot I do not see a valid kwargs that exists for what you are asking.
There exists mfc, mec, ms and mew which are markerfacecolor, markeredgecolor, markersize and markeredgewith. It can probably be asked in GitHub so that people take this into consideration and add it in the next version of matplotlib.
Also taking a look at the answer for this question asked in Stackoverflow, I don't believe it can be done.
Related
Is it possible to make a dashed linestyle using more complicated shapes in matplotlib (or any other python plotting library)? It's easy to make a linestyle with different spacings and combinations of dots and dashes, but I'm after something like this:
I can envision a way of doing it by writing a function from scratch to take a custom chevron marker style and working out the angle to display it at and the correct spacing etc. However that seems like an overly complicated way to address the problem that will easily break down for things like different specified line widths.
If you find a better latex symbol, you could do something like this.
import numpy as np
import matplotlib
matplotlib.rc('text', usetex=True)
matplotlib.rcParams['text.latex.preamble'] = [r'\boldmath', r'\usepackage{amsmath}', r'\usepackage{amssymb}', r'\usepackage{fontawesome}']
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot('111')
ax.plot(np.linspace(0,10,10),np.repeat(10,10),marker='$>$',ls='',ms=50,mew=10)
plt.show()
Look at the symbols in the fontawesome latex package, it might have something closer to what you're wanting. Then you can substitute the marker marker='$>$' for another latex symbol.
I’d like to employ the reverse Spectral colormap ,
https://matplotlib.org/examples/color/colormaps_reference.html
for a lineplot.
This works fine with a hex bin plot::
color_map = plt.cm.Spectral_r
image = plt.hexbin(x,y,cmap=color_map)
but when I do
ax1.plot(x,y, cmp=color_map)
this gives me::
AttributeError: Unknown property cmap
Note, I just want to set the colormap and let matplotliob do the rest; i.e. I don't want to have a color=' argument in the .plot command.
You can have a look at this solution - the third variant is what you want:
https://stackoverflow.com/a/57227821/5972778
You need to know how many lines you're plotting in advance, as otherwise it doesn't know how to choose the colours from the range.
I think that seaborn's color_palette function is very convenient for this purpose. It can be used in a with statement to temporarily set the color cycle for a plot or set of plots.
For example:
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
with sns.color_palette("Spectral", n_colors=10):
plt.plot(np.random.rand(5, 10))
You can use with any predefined matplotlib or seaborn colormap, or provide a custom sequence of colors.
Updated MRE with subplots
I'm not sure of the usefulness of the original question and MRE. The margin padding seems to be properly adjusted for large x and y labels.
The issue is reproducible with subplots.
Using matplotlib 3.4.2
fig, axes = plt.subplots(ncols=2, nrows=2, figsize=(8, 6))
axes = axes.flatten()
for ax in axes:
ax.set_ylabel(r'$\ln\left(\frac{x_a-x_b}{x_a-x_c}\right)$')
ax.set_xlabel(r'$\ln\left(\frac{x_a-x_d}{x_a-x_e}\right)$')
plt.show()
Original
I am plotting a dataset using matplotlib where I have an xlabel that is quite "tall" (it's a formula rendered in TeX that contains a fraction and is therefore has the height equivalent of a couple of lines of text).
In any case, the bottom of the formula is always cut off when I draw the figures. Changing figure size doesn't seem to help this, and I haven't been able to figure out how to shift the x-axis "up" to make room for the xlabel. Something like that would be a reasonable temporary solution, but what would be nice would be to have a way to make matplotlib recognize automatically that the label is cut off and resize accordingly.
Here's an example of what I mean:
import matplotlib.pyplot as plt
plt.figure()
plt.ylabel(r'$\ln\left(\frac{x_a-x_b}{x_a-x_c}\right)$')
plt.xlabel(r'$\ln\left(\frac{x_a-x_d}{x_a-x_e}\right)$', fontsize=50)
plt.title('Example with matplotlib 3.4.2\nMRE no longer an issue')
plt.show()
The entire ylabel is visible, however, the xlabel is cut off at the bottom.
In the case this is a machine-specific problem, I am running this on OSX 10.6.8 with matplotlib 1.0.0
Use:
import matplotlib.pyplot as plt
plt.gcf().subplots_adjust(bottom=0.15)
# alternate option without .gcf
plt.subplots_adjust(bottom=0.15)
to make room for the label, where plt.gcf() means get the current figure. plt.gca(), which gets the current Axes, can also be used.
Edit:
Since I gave the answer, matplotlib has added the plt.tight_layout() function.
See matplotlib Tutorials: Tight Layout Guide
So I suggest using it:
fig, axes = plt.subplots(ncols=2, nrows=2, figsize=(8, 6))
axes = axes.flatten()
for ax in axes:
ax.set_ylabel(r'$\ln\left(\frac{x_a-x_b}{x_a-x_c}\right)$')
ax.set_xlabel(r'$\ln\left(\frac{x_a-x_d}{x_a-x_e}\right)$')
plt.tight_layout()
plt.show()
In case you want to store it to a file, you solve it using bbox_inches="tight" argument:
plt.savefig('myfile.png', bbox_inches="tight")
An easy option is to configure matplotlib to automatically adjust the plot size. It works perfectly for me and I'm not sure why it's not activated by default.
Method 1
Set this in your matplotlibrc file
figure.autolayout : True
See here for more information on customizing the matplotlibrc file: http://matplotlib.org/users/customizing.html
Method 2
Update the rcParams during runtime like this
from matplotlib import rcParams
rcParams.update({'figure.autolayout': True})
The advantage of using this approach is that your code will produce the same graphs on differently-configured machines.
plt.autoscale() worked for me.
You can also set custom padding as defaults in your $HOME/.matplotlib/matplotlib_rc as follows. In the example below I have modified both the bottom and left out-of-the-box padding:
# The figure subplot parameters. All dimensions are a fraction of the
# figure width or height
figure.subplot.left : 0.1 #left side of the subplots of the figure
#figure.subplot.right : 0.9
figure.subplot.bottom : 0.15
...
There is also a way to do this using the OOP interface, applying tight_layout directly to a figure:
fig, ax = plt.subplots()
fig.set_tight_layout(True)
https://matplotlib.org/stable/api/figure_api.html
for some reason sharex was set to True so I turned it back to False and it worked fine.
df.plot(........,sharex=False)
You need to use sizzors to modify the axis-range:
import sizzors as sizzors_module
sizzors_module.reshape_the_axis(plt).save("literlymylief.tiff")
I'm using Python to plot a couple of graphs and I'm trying to change the formatting and essentially 'brand' the graph. I've managed to change most things using pylab.rcParams[...], but I can't work out how to change the colour of the markers on the axes and the border around the legend. Any help would be much appreciated. The line below is an example of the type of code I've been using to edit other parts. Basically just lines taken from matplotlibrc, but I can't find them to change everything I want.
pylab.rcParams[axes.labelcolor' = '#031F73'
If you just want to use rcParams, the proper parameters are xticks.color and yticks.color. I can't seem to find a key for the legend frame color. You can set that (along with the tick colors) programmatically though.
import pylab
pylab.plot([1,2,3],[4,5,6], label ='test')
lg = pylab.legend()
lg.get_frame().set_edgecolor('blue')
ax = pylab.axes()
for line in ax.yaxis.get_ticklines():
line.set_color('blue')
for line in ax.xaxis.get_ticklines():
line.set_color('blue')
for label in ax.yaxis.get_ticklabels():
label.set_color('blue')
for label in ax.xaxis.get_ticklabels():
label.set_color('blue')
pylab.show()
How can I flip the origin of a matplotlib plot to be in the upper-left corner - as opposed to the default lower-left? I'm using matplotlib.pylab.plot to produce the plot (though if there is another plotting routine that is more flexible, please let me know).
I'm looking for the equivalent of the matlab command: axis ij;
Also, I've spent a couple hours surfing matplotlib help and google but haven't come up with an answer. Some info on where I could have looked up the answer would be helpful as well.
The easiest way is to use:
plt.gca().invert_yaxis()
After you plotted the image. Origin works only for imshow.
axis ij just makes the y-axis increase downward instead of upward, right? If so, then matplotlib.axes.invert_yaxis() might be all you need -- but I can't test that right now.
If that doesn't work, I found a mailing post suggesting that
setp(gca(), 'ylim', reversed(getp(gca(), 'ylim')))
might do what you want to resemble axis ij.
For an image or contour plot, you can use the keyword origin = None | 'lower' | 'upper' and for a line plot, you can set the ylimits high to low.
from pylab import *
A = arange(25)/25.
A = A.reshape((5,5))
figure()
imshow(A, interpolation='nearest', origin='lower')
figure()
imshow(A, interpolation='nearest')
d = arange(5)
figure()
plot(d)
ylim(5, 0)
show()
The following is a basic way to achieve this
ax=pylab.gca()
ax.set_ylim(ax.get_ylim()[::-1])
This
plt.ylim(max(plt.ylim()), min(plt.ylim()))
has an advantage over this
plt.gca().invert_yaxis()
and is that if you are in interactive mode and you repeatedly plot the same plot (maybe with updated data and having a breakpoint after the plot) the y axis won't keep inverting every time.