How to change marker border width and hatch width? - python

In this example of a marker from my scatter plot I have set the color to green, and edge color to black, and hatch to "|". For the hatch pattern to show up at all I must set the edgecolor, however when I do, I get a very thick border around the marker. Two questions:
1) How can I to set the size of this border (preferably to 0)?
2) How can I increase the thickness of the hatch lines?

You just need to set the linewidth to control the marker border thickness.
You can increase the density of hatching, by repeating symbols (in the example below, the '|' is repeated in the R/H pane; note that to obtain NW->SE diagonal lines the symbol must be escaped so needs twice as many characters to really double it -- '\\\\' is density 2 while '||||' is density 4). However, I don't think the thickness of individual lines within hatching is controllable.
See the code example below to produce scatter plots such as these:
import matplotlib.pyplot as plt
# generate some data
x = [1,2,3,4,5,8]
y= [i**2 for i in x]
y2= [60-i**2+3*i for i in x]
# plot markers with thick borders
plt.subplot(121)
plt.scatter(x,y, s=500, marker='s', edgecolor='black', linewidth=3, facecolor='green', hatch='|')
# compare with no borders, and denser hatch.
plt.subplot(122)
plt.scatter(x,y2, s=500, marker='s', edgecolor='black', linewidth=0, facecolor='green', hatch='||||')
plt.show()
matplotlib documentation on collections
and scatter.

This is several years after you asked the question, but the only way I've found to do it is to change the matplotlib.rc.
You can do this either in the actual .rc file or within your python script, e.g.
import matplotlib as mpl
mpl.rc('hatch', color='k', linewidth=1.5)
This will make all of the hatch lines in your script black and thickness 1.5 rather than the default 1.0.

If you're using plt.plot, you'll want to pass argument markeredgewidth.

Related

Matplotlib: how to set line color to orange, and specify line markers?

I have a situation where I have many lines that I am plotting in pyplot.
They are grouped by color, and within each color, I plot according to plot style--so the circles, dashes, etc.
My plot styling is:
plt.plot(x,y1,'b')
plt.plot(x,y2,'bs')
plt.plot(x,y3,'b--')
And then I repeat for various colors. However, I am running into trouble with orange. When I plot with orange, I get an error because pyplot wants to plot with circles instead of the color orange! Here is an example:
plt.plot(x,z1,'o')
plt.plot(x,z2,'os')
plt.plot(x,z3,'o--')
This fails because 'os' is being parsed as two formatting instructions, rather than a color and the format: squares.
How do I work around this in order to plot the orange lines?
That is because the character 'o' is not a pre-defined single-letter color code. You will instead need to use either the RGB value or the string 'orange' as your color specification (see below).
plt.plot(x, z3, '--', color='orange') % String colorspec
plt.plot(x, z3, '--', color='#FFA500') % Hex colorspec
plt.plot(x, z3, '--', color=[1.0, 0.5, 0.25]) % RGB colorspec
"o" is not one of the available color codes.
An alternative to plt.plot(x,z3,'o--') is, for example,
plt.plot(x, z3, '--', color="orange")
Use HTML colour codes to specify the colour of your plot. Something along the lines of ->
plt.plot(x,y,'o',color='#F39C12')
This plots x,y with orange circles.
orange circles look pretty with sinusiods
Edit: You can nitpick your color at http://htmlcolorcodes.com/

Matplotlib control which plot is on top

I am wondering if there is a way to control which plot lies on top of other plots if one makes multiple plots on one axis. An example:
As you can see, the green series is on top of the blue series, and both series are on top of the black dots (which I made with a scatter plot). I would like the black dots to be on top of both series (lines).
I first did the above with the following code
plt.plot(series1_x, series1_y)
plt.plot(series2_x, series2_y)
plt.scatter(series2_x, series2_y)
Then I tried the following
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.plot(series1_x, series1_y)
ax2 = fig.add_subplot(111)
ax2.plot(series2_x, series2_y)
ax3 = fig.add_subplot(111)
ax3.scatter(series2_x, series2_y)
And some variations on that, but no luck.
Swapping around the plot functions has an effect on which plot is on top, but no matter where I put the scatter function, the lines are on top of the dots.
NOTE:
I am using Python 3.5 on Windows 10 (this example), but mostly Python 3.4 on Ubuntu.
NOTE 2:
I know this may seem like a trivial issue, but I have a case where the series on top of the dots are so dense that the colour of the dots get obscured, and in those cases I need my readers to clearly see which dots are what colour, hence why I need the dots to be on top.
Use the zorder kwarg where the lower the zorder the further back the plot, e.g.
plt.plot(series1_x, series1_y, zorder=1)
plt.plot(series2_x, series2_y, zorder=2)
plt.scatter(series2_x, series2_y, zorder=3)
Yes, you can. Just use zorder parameter. The higher the value, more on top the plot shall be.
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.plot(series1_x, series1_y, zorder=3)
ax2 = fig.add_subplot(111)
ax2.plot(series2_x, series2_y, zorder=4)
ax3 = fig.add_subplot(111)
ax3.scatter(series2_x, series2_y, zorder=5)
Alternatively, you can do line and marker plot at the same time. You can even set different colors for line and marker face.
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.plot(series1_x, series1_y)
ax2 = fig.add_subplot(111)
ax2.plot(series2_x, series2_y, '-o', color='b', mfc='k')
The '-o' sets plot style to line and circle markers, color='b' sets line color to blue and mfc='k' sets the marker face color to black.
Another solution besides using zorder, and worth knowing: You can simply plot a scatter of points using the plot command. Something like plot(series2_x, series2_y, ' o'). Note the ' o' with a space means no lines but circle points. This way the order of plotting them on the axes does put them on top.

matplotlib: how to change colors, make little spaces and edit the legend

I have the following code to draw some lines in matplotlib. I have tried to make the points be shown with transparent circles rather than the standard solid filled in circles.
How can I make the circles be the same color as the lines?
How can I remove the circles from the ends of the dashed lines in the legend? Currently you can hardly see the dashed lines.
How can I make a little gap before and after each circle in the graph so the dashed lines don't touch them. I think this would look better here as I only have data at the points so the lines in between don't represent real data.
import matplotlib.pyplot as plt
import numpy as np
t = np.array([0.19641715476064042,
0.25,
0.34,
0.42])
c = np.array([0.17,
0.21,
0.27,
0.36])
plt.plot(t, '-go', markerfacecolor='w', linestyle= 'dashed', label='n=20')
plt.plot(c, '-bo', markerfacecolor='w', linestyle= 'dashed', label='n=22')
plt.show()
This is what the matplotlib code currently gives me.
This is what I would like it to ultimately look like (clearly with different data).
Beware that you seem to misuse the fmt format string (like "-go") in your calls to plot. In fact for a dashed line fmt should be more something like "--go".
I personally tend to find the use of keyword arguments clearer even if more verbose (in your case, linestyle="dashed" prevails on fmt string)
http://matplotlib.org/api/axes_api.html?highlight=plot#matplotlib.axes.Axes.plot
Anyway, below a tentative to reproduce the desired plot:
import matplotlib.pyplot as plt
import numpy as np
t = np.array([0.19641715476064042,
0.25, 0.34, 0.42])
c = np.array([0.17, 0.21, 0.27, 0.36])
def my_plot(ax, tab, c="g", ls="-", marker="o", ms=6, mfc="w", mec="g", label="",
zorder=2):
"""
tab: array to plot
c: line color (default green)
ls: linestyle (default solid line)
marker: kind of marker
ms: markersize
mfc: marker face color
mec: marker edge color
label: legend label
"""
ax.plot(tab, c=c, ms=0, ls=ls, label=label, zorder=zorder-0.02)
ax.plot(tab, c=c, marker=marker, ms=ms, mec=mec, mfc=mfc, ls="none",
zorder=zorder)
ax.plot(tab, c=c, marker=marker, ms=ms*4, mfc="w", mec="w", ls="none",
zorder=zorder-0.01)
my_plot(plt, t, c="g", mec="g", ls="dashed", label="n=20")
my_plot(plt, c, c="b", mec="b", ls="dashed", label="n=22")
plt.legend(loc=2)
plt.show()
Also consider reading the legend guide in the official documentation:
http://matplotlib.org/users/legend_guide.html?highlight=legend%20guide
For the first question, you use the markeredgecolor attribute:
plt.plot(t, '-go', markerfacecolor='w', markeredgecolor='g', linestyle= 'dotted', label='n=20')
plt.plot(c, '-bo', markerfacecolor='w', markeredgecolor='b', linestyle= 'dotted', label='n=22')
As for the third question, I have no idea. I don't think there is an easy way to do this. But I guess you could, for example, do the following:
Plot the line
Plot solid white markers that are slightly larger than those you have now (edge and face color white). These will mask out parts of the line around the real markers.
Plot the real markers using the required color.

How does vary the brightness of markers on a Matplotlib basemap?

This code varies the transparency of markers on a matplotlib base map via the alpha parameter.
myBaseMap.plot(x_values, y_values, 'x', alpha=0.7, c=(1.,0,0))
However, how does one vary the brightness of a marker? I do not want semi-transparent markers because I want the markers to cover the content behind them. Thank you!
My reading of your question is that you would like to know how to get different transparency for line and markers.
One way to do this is to plot the markers using scatter:
myBaseMap.plot(x_values, y_values, alpha=0.7, c=(1.,0,0), zorder=0)
myBaseMap.scatter(x_values, y_values, marker='x', color=(1.,0,0), zorder=1)
Lower zorder numbers are drawn first.
Simple example:
import matplotlib.pyplot as plt
plt.plot([1,2,3],[3,2,1],alpha=0.25,c=(1.,0,0),zorder=0)
plt.scatter([1,2,3],[3,2,1],marker='x',color=(1.,0,0),zorder=1,s=75,alpha=1.0)
If you want to vary the brightness, like dark red versus light red, then you could linearly vary the color from (0,0,0), which is black, to (1,0,0), which is red, to (1,1,1), which is white, leaving alpha alone.
But I'm not very sure this is what you want...

How to do a scatter plot with empty circles in Python?

In Python, with Matplotlib, how can a scatter plot with empty circles be plotted? The goal is to draw empty circles around some of the colored disks already plotted by scatter(), so as to highlight them, ideally without having to redraw the colored circles.
I tried facecolors=None, to no avail.
From the documentation for scatter:
Optional kwargs control the Collection properties; in particular:
edgecolors:
The string ‘none’ to plot faces with no outlines
facecolors:
The string ‘none’ to plot unfilled outlines
Try the following:
import matplotlib.pyplot as plt
import numpy as np
x = np.random.randn(60)
y = np.random.randn(60)
plt.scatter(x, y, s=80, facecolors='none', edgecolors='r')
plt.show()
Note: For other types of plots see this post on the use of markeredgecolor and markerfacecolor.
Would these work?
plt.scatter(np.random.randn(100), np.random.randn(100), facecolors='none')
or using plot()
plt.plot(np.random.randn(100), np.random.randn(100), 'o', mfc='none')
Here's another way: this adds a circle to the current axes, plot or image or whatever :
from matplotlib.patches import Circle # $matplotlib/patches.py
def circle( xy, radius, color="lightsteelblue", facecolor="none", alpha=1, ax=None ):
""" add a circle to ax= or current axes
"""
# from .../pylab_examples/ellipse_demo.py
e = Circle( xy=xy, radius=radius )
if ax is None:
ax = pl.gca() # ax = subplot( 1,1,1 )
ax.add_artist(e)
e.set_clip_box(ax.bbox)
e.set_edgecolor( color )
e.set_facecolor( facecolor ) # "none" not None
e.set_alpha( alpha )
(The circles in the picture get squashed to ellipses because imshow aspect="auto" ).
In matplotlib 2.0 there is a parameter called fillstyle
which allows better control on the way markers are filled.
In my case I have used it with errorbars but it works for markers in general
http://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.errorbar.html
fillstyle accepts the following values: [‘full’ | ‘left’ | ‘right’ | ‘bottom’ | ‘top’ | ‘none’]
There are two important things to keep in mind when using fillstyle,
1) If mfc is set to any kind of value it will take priority, hence, if you did set fillstyle to 'none' it would not take effect.
So avoid using mfc in conjuntion with fillstyle
2) You might want to control the marker edge width (using markeredgewidth or mew) because if the marker is relatively small and the edge width is thick, the markers will look like filled even though they are not.
Following is an example using errorbars:
myplot.errorbar(x=myXval, y=myYval, yerr=myYerrVal, fmt='o', fillstyle='none', ecolor='blue', mec='blue')
Basend on the example of Gary Kerr and as proposed here one may create empty circles related to specified values with following code:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.markers import MarkerStyle
x = np.random.randn(60)
y = np.random.randn(60)
z = np.random.randn(60)
g=plt.scatter(x, y, s=80, c=z)
g.set_facecolor('none')
plt.colorbar()
plt.show()
So I assume you want to highlight some points that fit a certain criteria. You can use Prelude's command to do a second scatter plot of the hightlighted points with an empty circle and a first call to plot all the points. Make sure the s paramter is sufficiently small for the larger empty circles to enclose the smaller filled ones.
The other option is to not use scatter and draw the patches individually using the circle/ellipse command. These are in matplotlib.patches, here is some sample code on how to draw circles rectangles etc.

Categories