Matplotlib control which plot is on top - python

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.

Related

How i can delete xlabel of plot? [duplicate]

I'm trying to plot a figure without tickmarks or numbers on either of the axes (I use axes in the traditional sense, not the matplotlib nomenclature!). An issue I have come across is where matplotlib adjusts the x(y)ticklabels by subtracting a value N, then adds N at the end of the axis.
This may be vague, but the following simplified example highlights the issue, with '6.18' being the offending value of N:
import matplotlib.pyplot as plt
import random
prefix = 6.18
rx = [prefix+(0.001*random.random()) for i in arange(100)]
ry = [prefix+(0.001*random.random()) for i in arange(100)]
plt.plot(rx,ry,'ko')
frame1 = plt.gca()
for xlabel_i in frame1.axes.get_xticklabels():
xlabel_i.set_visible(False)
xlabel_i.set_fontsize(0.0)
for xlabel_i in frame1.axes.get_yticklabels():
xlabel_i.set_fontsize(0.0)
xlabel_i.set_visible(False)
for tick in frame1.axes.get_xticklines():
tick.set_visible(False)
for tick in frame1.axes.get_yticklines():
tick.set_visible(False)
plt.show()
The three things I would like to know are:
How to turn off this behaviour in the first place (although in most cases it is useful, it is not always!) I have looked through matplotlib.axis.XAxis and cannot find anything appropriate
How can I make N disappear (i.e. X.set_visible(False))
Is there a better way to do the above anyway? My final plot would be 4x4 subplots in a figure, if that is relevant.
Instead of hiding each element, you can hide the whole axis:
frame1.axes.get_xaxis().set_visible(False)
frame1.axes.get_yaxis().set_visible(False)
Or, you can set the ticks to an empty list:
frame1.axes.get_xaxis().set_ticks([])
frame1.axes.get_yaxis().set_ticks([])
In this second option, you can still use plt.xlabel() and plt.ylabel() to add labels to the axes.
If you want to hide just the axis text keeping the grid lines:
frame1 = plt.gca()
frame1.axes.xaxis.set_ticklabels([])
frame1.axes.yaxis.set_ticklabels([])
Doing set_visible(False) or set_ticks([]) will also hide the grid lines.
If you are like me and don't always retrieve the axes, ax, when plotting the figure, then a simple solution would be to do
plt.xticks([])
plt.yticks([])
I've colour coded this figure to ease the process.
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
You can have full control over the figure using these commands, to complete the answer I've add also the control over the spines:
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
# X AXIS -BORDER
ax.spines['bottom'].set_visible(False)
# BLUE
ax.set_xticklabels([])
# RED
ax.set_xticks([])
# RED AND BLUE TOGETHER
ax.axes.get_xaxis().set_visible(False)
# Y AXIS -BORDER
ax.spines['left'].set_visible(False)
# YELLOW
ax.set_yticklabels([])
# GREEN
ax.set_yticks([])
# YELLOW AND GREEN TOGHETHER
ax.axes.get_yaxis().set_visible(False)
I was not actually able to render an image without borders or axis data based on any of the code snippets here (even the one accepted at the answer). After digging through some API documentation, I landed on this code to render my image
plt.axis('off')
plt.tick_params(axis='both', left=False, top=False, right=False, bottom=False, labelleft=False, labeltop=False, labelright=False, labelbottom=False)
plt.savefig('foo.png', dpi=100, bbox_inches='tight', pad_inches=0.0)
I used the tick_params call to basically shut down any extra information that might be rendered and I have a perfect graph in my output file.
Somewhat of an old thread but, this seems to be a faster method using the latest version of matplotlib:
set the major formatter for the x-axis
ax.xaxis.set_major_formatter(plt.NullFormatter())
One trick could be setting the color of tick labels as white to hide it!
plt.xticks(color='w')
plt.yticks(color='w')
or to be more generalized (#Armin Okić), you can set it as "None".
When using the object oriented API, the Axes object has two useful methods for removing the axis text, set_xticklabels() and set_xticks().
Say you create a plot using
fig, ax = plt.subplots(1)
ax.plot(x, y)
If you simply want to remove the tick labels, you could use
ax.set_xticklabels([])
or to remove the ticks completely, you could use
ax.set_xticks([])
These methods are useful for specifying exactly where you want the ticks and how you want them labeled. Passing an empty list results in no ticks, or no labels, respectively.
You could simply set xlabel to None, straight in your axis. Below an working example using seaborn
from matplotlib import pyplot as plt
import seaborn as sns
tips = sns.load_dataset("tips")
ax = sns.boxplot(x="day", y="total_bill", data=tips)
ax.set(xlabel=None)
plt.show()
Just do this in case you have subplots
fig, axs = plt.subplots(1, 2, figsize=(16, 8))
ax[0].set_yticklabels([]) # x-axis
ax[0].set_xticklabels([]) # y-axis

Adding secondary y labels to heatmap in matplotlib [duplicate]

I'm trying to plot a two-dimensional array in matplotlib using imshow(), and overlay it with a scatterplot on a second y axis.
oneDim = np.array([0.5,1,2.5,3.7])
twoDim = np.random.rand(8,4)
plt.figure()
ax1 = plt.gca()
ax1.imshow(twoDim, cmap='Purples', interpolation='nearest')
ax1.set_xticks(np.arange(0,twoDim.shape[1],1))
ax1.set_yticks(np.arange(0,twoDim.shape[0],1))
ax1.set_yticklabels(np.arange(0,twoDim.shape[0],1))
ax1.grid()
#This is the line that causes problems
ax2 = ax1.twinx()
#That's not really part of the problem (it seems)
oneDimX = oneDim.shape[0]
oneDimY = 4
ax2.plot(np.arange(0,oneDimX,1),oneDim)
ax2.set_yticks(np.arange(0,oneDimY+1,1))
ax2.set_yticklabels(np.arange(0,oneDimY+1,1))
If I only run everything up to the last line, I get my array fully visualised:
However, if I add a second y axis (ax2=ax1.twinx()) as preparation for the scatterplot, it changes to this incomplete rendering:
What's the problem? I've left a few lines in the code above describing the addition of the scatterplot, although it doesn't seem to be part of the issue.
Following the GitHub discussion which Thomas Kuehn has pointed at, the issue has been fixed few days ago. In the absence of a readily available built, here's a fix using the aspect='auto' property. In order to get nice regular boxes, I adjusted the figure x/y using the array dimensions. The axis autoscale feature has been used to remove some additional white border.
oneDim = np.array([0.5,1,2.5,3.7])
twoDim = np.random.rand(8,4)
plt.figure(figsize=(twoDim.shape[1]/2,twoDim.shape[0]/2))
ax1 = plt.gca()
ax1.imshow(twoDim, cmap='Purples', interpolation='nearest', aspect='auto')
ax1.set_xticks(np.arange(0,twoDim.shape[1],1))
ax1.set_yticks(np.arange(0,twoDim.shape[0],1))
ax1.set_yticklabels(np.arange(0,twoDim.shape[0],1))
ax1.grid()
ax2 = ax1.twinx()
#Required to remove some white border
ax1.autoscale(False)
ax2.autoscale(False)
Result:

add_axes covers previous plot

I am making a 3D plot with two sets of axes (in particular, an animation for a rotating cone).
First, I make one set of axes using fig.add_subplot, and plot the rotating cone using ax.plot.
fig=plt.figure()
ax = fig.add_subplot(111, projection="3d")
But when I add this declaration for ax2 after the above two lines (like below), I just see a white plot (no rotating cone).
fig=plt.figure()
ax = fig.add_subplot(111, projection="3d")
ax2 = fig.add_axes(ax.get_position(), projection="3d", frame_on=False)
Can anyone help with what went wrong here? Why is what I plotted using ax get covered or erased when I declared an ax2?
Thanks!
The second plot background color is covering the first one. You can remove the background by doing:
ax2.patch.set_visible(False)
However, you will still see the second axes on top of the first one, and you will only be able to interact with the top axes and not the bottom one. Are you sure that's what you are trying to do?

Remove text from figure when using dataframe.boxplot(by=...) [duplicate]

I'm trying to plot a figure without tickmarks or numbers on either of the axes (I use axes in the traditional sense, not the matplotlib nomenclature!). An issue I have come across is where matplotlib adjusts the x(y)ticklabels by subtracting a value N, then adds N at the end of the axis.
This may be vague, but the following simplified example highlights the issue, with '6.18' being the offending value of N:
import matplotlib.pyplot as plt
import random
prefix = 6.18
rx = [prefix+(0.001*random.random()) for i in arange(100)]
ry = [prefix+(0.001*random.random()) for i in arange(100)]
plt.plot(rx,ry,'ko')
frame1 = plt.gca()
for xlabel_i in frame1.axes.get_xticklabels():
xlabel_i.set_visible(False)
xlabel_i.set_fontsize(0.0)
for xlabel_i in frame1.axes.get_yticklabels():
xlabel_i.set_fontsize(0.0)
xlabel_i.set_visible(False)
for tick in frame1.axes.get_xticklines():
tick.set_visible(False)
for tick in frame1.axes.get_yticklines():
tick.set_visible(False)
plt.show()
The three things I would like to know are:
How to turn off this behaviour in the first place (although in most cases it is useful, it is not always!) I have looked through matplotlib.axis.XAxis and cannot find anything appropriate
How can I make N disappear (i.e. X.set_visible(False))
Is there a better way to do the above anyway? My final plot would be 4x4 subplots in a figure, if that is relevant.
Instead of hiding each element, you can hide the whole axis:
frame1.axes.get_xaxis().set_visible(False)
frame1.axes.get_yaxis().set_visible(False)
Or, you can set the ticks to an empty list:
frame1.axes.get_xaxis().set_ticks([])
frame1.axes.get_yaxis().set_ticks([])
In this second option, you can still use plt.xlabel() and plt.ylabel() to add labels to the axes.
If you want to hide just the axis text keeping the grid lines:
frame1 = plt.gca()
frame1.axes.xaxis.set_ticklabels([])
frame1.axes.yaxis.set_ticklabels([])
Doing set_visible(False) or set_ticks([]) will also hide the grid lines.
If you are like me and don't always retrieve the axes, ax, when plotting the figure, then a simple solution would be to do
plt.xticks([])
plt.yticks([])
I've colour coded this figure to ease the process.
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
You can have full control over the figure using these commands, to complete the answer I've add also the control over the spines:
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
# X AXIS -BORDER
ax.spines['bottom'].set_visible(False)
# BLUE
ax.set_xticklabels([])
# RED
ax.set_xticks([])
# RED AND BLUE TOGETHER
ax.axes.get_xaxis().set_visible(False)
# Y AXIS -BORDER
ax.spines['left'].set_visible(False)
# YELLOW
ax.set_yticklabels([])
# GREEN
ax.set_yticks([])
# YELLOW AND GREEN TOGHETHER
ax.axes.get_yaxis().set_visible(False)
I was not actually able to render an image without borders or axis data based on any of the code snippets here (even the one accepted at the answer). After digging through some API documentation, I landed on this code to render my image
plt.axis('off')
plt.tick_params(axis='both', left=False, top=False, right=False, bottom=False, labelleft=False, labeltop=False, labelright=False, labelbottom=False)
plt.savefig('foo.png', dpi=100, bbox_inches='tight', pad_inches=0.0)
I used the tick_params call to basically shut down any extra information that might be rendered and I have a perfect graph in my output file.
Somewhat of an old thread but, this seems to be a faster method using the latest version of matplotlib:
set the major formatter for the x-axis
ax.xaxis.set_major_formatter(plt.NullFormatter())
One trick could be setting the color of tick labels as white to hide it!
plt.xticks(color='w')
plt.yticks(color='w')
or to be more generalized (#Armin Okić), you can set it as "None".
When using the object oriented API, the Axes object has two useful methods for removing the axis text, set_xticklabels() and set_xticks().
Say you create a plot using
fig, ax = plt.subplots(1)
ax.plot(x, y)
If you simply want to remove the tick labels, you could use
ax.set_xticklabels([])
or to remove the ticks completely, you could use
ax.set_xticks([])
These methods are useful for specifying exactly where you want the ticks and how you want them labeled. Passing an empty list results in no ticks, or no labels, respectively.
You could simply set xlabel to None, straight in your axis. Below an working example using seaborn
from matplotlib import pyplot as plt
import seaborn as sns
tips = sns.load_dataset("tips")
ax = sns.boxplot(x="day", y="total_bill", data=tips)
ax.set(xlabel=None)
plt.show()
Just do this in case you have subplots
fig, axs = plt.subplots(1, 2, figsize=(16, 8))
ax[0].set_yticklabels([]) # x-axis
ax[0].set_xticklabels([]) # y-axis

Matplotlib pyplot - Plot graph with framelines [duplicate]

I want to get both horizontal and vertical grid lines on my plot but only the horizontal grid lines are appearing by default. I am using a pandas.DataFrame from an sql query in python to generate a line plot with dates on the x-axis. I'm not sure why they do not appear on the dates and I have tried to search for an answer to this but couldn't find one.
All I have used to plot the graph is the simple code below.
data.plot()
grid('on')
data is the DataFrame which contains the dates and the data from the sql query.
I have also tried adding the code below but I still get the same output with no vertical grid lines.
ax = plt.axes()
ax.yaxis.grid() # horizontal lines
ax.xaxis.grid() # vertical lines
Any suggestions?
You may need to give boolean arg in your calls, e.g. use ax.yaxis.grid(True) instead of ax.yaxis.grid(). Additionally, since you are using both of them you can combine into ax.grid, which works on both, rather than doing it once for each dimension.
ax = plt.gca()
ax.grid(True)
That should sort you out.
plt.gca().xaxis.grid(True) proved to be the solution for me
According to matplotlib documentation, The signature of the Axes class grid() method is as follows:
Axes.grid(b=None, which='major', axis='both', **kwargs)
Turn the axes grids on or off.
which can be ‘major’ (default), ‘minor’, or ‘both’ to control whether
major tick grids, minor tick grids, or both are affected.
axis can be ‘both’ (default), ‘x’, or ‘y’ to control which set of
gridlines are drawn.
So in order to show grid lines for both the x axis and y axis, we can use the the following code:
ax = plt.gca()
ax.grid(which='major', axis='both', linestyle='--')
This method gives us finer control over what to show for grid lines.
Short answer (read below for more info):
ax.grid(axis='both', which='both')
What you do is correct and it should work.
However, since the X axis in your example is a DateTime axis the Major tick-marks (most probably) are appearing only at the both ends of the X axis. The other visible tick-marks are Minor tick-marks.
The ax.grid() method, by default, draws grid lines on Major tick-marks.
Therefore, nothing appears in your plot.
Use the code below to highlight the tick-marks. Majors will be Blue while Minors are Red.
ax.tick_params(which='both', width=3)
ax.tick_params(which='major', length=20, color='b')
ax.tick_params(which='minor', length=10, color='r')
Now to force the grid lines to be appear also on the Minor tick-marks, pass the which='minor' to the method:
ax.grid(b=True, which='minor', axis='x', color='#000000', linestyle='--')
or simply use which='both' to draw both Major and Minor grid lines.
And this a more elegant grid line:
ax.grid(b=True, which='minor', axis='both', color='#888888', linestyle='--')
ax.grid(b=True, which='major', axis='both', color='#000000', linestyle='-')
maybe this can solve the problem:
matplotlib, define size of a grid on a plot
ax.grid(True, which='both')
The truth is that the grid is working, but there's only one v-grid in 00:00 and no grid in others. I meet the same problem that there's only one grid in Nov 1 among many days.
For only horizontal lines
ax = plt.axes()
ax.yaxis.grid() # horizontal lines
This worked
Try:
plt.grid(True)
This turns on both horizontal and vertical grids for date series with major tick marks in the right place.
Using Python3 / MatPlotLib 3.4.3

Categories