I am plotting some values in a semilogy plot. I need to use the
ax.set_yscale('log')
rather than
ax.semilogy(...
because i have some arrays with negative values (so I can set the scale to symlog).
My code
ax = plt.subplot(132)
ax.set_yscale('log')
ax.plot(np.arange(0,4),array,'-o')
ax.errorbar(np.arange(0,4),array,yerr=[yerr_neg,yerr_pos])
ax.set_yticks(np.exp(np.arange(-0.4,0.5,0.1)))
ax.set_yticklabels(np.arange(-0.4,0.5,0.1))
however the automatically placed ticks and labels are still there:
how do I properly get rid of the original ticks/labels? I get still the same error by eliminating either plot line (meaning deleting the ax.plot line or the ax.errorbar line)
The labels shown are minor ticklabels. You may set the minor ticks to an empty list to get rid of them.
ax.set_yticks([], minor=True)
or just set the minor ticks off,
ax.minorticks_off()
Related
I have this simple piece of code where I try to plot simple graph while limiting number of x ticks. There are hundreds of items in iters variable and if they get plotted it would just create one fat black line.
However, ax.locator_params does not work and the number of ticks aren't reduced.
I have tried setting it on plt object, but no help.
I also tried specifying x and y axes in locator_params, but no help as well.
Finally, I have tried moving ax.locator_params before and after ax.plot, but nothing seemed to help. I am completely out of ideas.
fig, ax = plt.subplots(1, 1, figsize=(20,10))
ax.locator_params(tight=True, nbins=4)
ax.plot(iters, vals)
plt.xticks(rotation=30)
plt.show()
locator_params() with nbins= is only supported for numerical axes where the tick positions are set via MaxNLocator.
To get the same effect with text ticks, the current ticks can be stored in a list (get_xticks) and then be replaced by a subset. Note that changes to ticks (and to limits) should be called after the main plot functions.
xticks = ax.get_xticks()
ax.set_xticks(xticks[::len(xticks) // 4]) # set new tick positions
ax.tick_params(axis='x', rotation=30) # set tick rotation
ax.margins(x=0) # set tight margins
I am drawing histograms for 4 different distributions using subplots. During the final output, I am getting tick labels for the y-axis for the fourth subplot. How shall I ensure it doesn't happen.
fig,((ax1,ax2),(ax3,ax4)) = plt.subplots(2,2,sharex=True,sharey=True)
plt.cla()
nbins = np.arange(-10,10,1)
ax1.hist(x1,bins=nbins)
ax1.set_title('Normal Distribution')
ax1.set_ylabel('Frequency')
ax2.hist(x2,bins=nbins)
ax2.set_title('Exponential Distribution')
ax3.hist(x3,bins=nbins)
ax3.set_title('Rayleigh Distribution')
ax3.set_xlabel('Value')
ax3.set_ylabel('Frequency')
ax4.hist(x4,bins=nbins)
ax4.set_title('Random Distribution')
ax4.set_xlabel('Value')
Here is the figure I am obtaining after running the code:
After adding the following code, it removed y-tick labels for other axes too
ax4.set_yticklabels([])
Following is the graph -
This is strange, as I cannot reproduce that behavior. I don't know why ax4 would behave differently from the other axes.
But in any case, since the axes are shared, you cannot just remove the tick labels since that removes them everywhere, as you've discovered. The solution is to make them invisible on the desired ax.
plt.setp(ax4.get_xticklabels(), visible=False)
I am plotting some values in a semilogy plot. I need to use the
ax.set_yscale('log')
rather than
ax.semilogy(...
because i have some arrays with negative values (so I can set the scale to symlog).
My code
ax = plt.subplot(132)
ax.set_yscale('log')
ax.plot(np.arange(0,4),array,'-o')
ax.errorbar(np.arange(0,4),array,yerr=[yerr_neg,yerr_pos])
ax.set_yticks(np.exp(np.arange(-0.4,0.5,0.1)))
ax.set_yticklabels(np.arange(-0.4,0.5,0.1))
however the automatically placed ticks and labels are still there:
how do I properly get rid of the original ticks/labels? I get still the same error by eliminating either plot line (meaning deleting the ax.plot line or the ax.errorbar line)
The labels shown are minor ticklabels. You may set the minor ticks to an empty list to get rid of them.
ax.set_yticks([], minor=True)
or just set the minor ticks off,
ax.minorticks_off()
I created a matplotlib plot that has 2 y-axes. The y-axes have different scales, but I want the ticks and grid to be aligned. I am pulling the data from excel files, so there is no way to know the max limits beforehand. I have tried the following code.
# creates double-y axis
ax2 = ax1.twinx()
locs = ax1.yaxis.get_ticklocs()
ax2.set_yticks(locs)
The problem now is that the ticks on ax2 do not have labels anymore. Can anyone give me a good way to align ticks with different scales?
Aligning the tick locations of two different scales would mean to give up on the nice automatic tick locator and set the ticks to the same positions on the secondary axes as on the original one.
The idea is to establish a relation between the two axes scales using a function and set the ticks of the second axes at the positions of those of the first.
import matplotlib.pyplot as plt
import matplotlib.ticker
fig, ax = plt.subplots()
# creates double-y axis
ax2 = ax.twinx()
ax.plot(range(5), [1,2,3,4,5])
ax2.plot(range(6), [13,17,14,13,16,12])
ax.grid()
l = ax.get_ylim()
l2 = ax2.get_ylim()
f = lambda x : l2[0]+(x-l[0])/(l[1]-l[0])*(l2[1]-l2[0])
ticks = f(ax.get_yticks())
ax2.yaxis.set_major_locator(matplotlib.ticker.FixedLocator(ticks))
plt.show()
Note that this is a solution for the general case and it might result in totally unreadable labels depeding on the use case. If you happen to have more a priori information on the axes range, better solutions may be possible.
Also see this question for a case where automatic tick locations of the first axes is sacrificed for an easier setting of the secondary axes tick locations.
To anyone who's wondering (and for my future reference), the lambda function f in ImportanceofBeingErnest's answer maps the input left tick to a corresponding right tick through:
RHS tick = Bottom RHS tick + (% of LHS range traversed * RHS range)
Refer to this question on tick formatting to truncate decimal places:
from matplotlib.ticker import FormatStrFormatter
ax2.yaxis.set_major_formatter(FormatStrFormatter('%.2f')) # ax2 is the RHS y-axis
Is there a way to anchor the ticks and tick labels of the x-axis so that they cross the y-axis at a different location than where the actual x-axis crosses the y-axis? This can basically be accomplished with:
ax = plt.gca()
ax.get_xaxis().set_tick_params(pad=5)
or
ax.xaxis.set_tick_params(pad=500)
For example:
Except that I am working with audio file inputs and the y-axis is variable (based on the highest/lowest amplitude of the waveform). Therefore, the maximum and minimum y-axis values change depending on the audio file. I am concerned that pad=NUM will be moving around relative to the y-axis.
Therefore, I am looking for a way to accomplish what pad does, but have the ticks and tick labels be anchored at the minimum y-axis value.
As a bonus, flipping this around so that the y-axis is anchored somewhere differently than the y-axis tick labels would surely benefit someone also.
In my particular case, I have the x-axis crossing the y-axis at y=0. The x-axis ticks and tick labels will sometimes be at -1.0, sometimes at -0.5, sometimes at -0.25, etc. I always know what the minimum value of the y-axis is, and therefore want it to be the anchor point for x-axis ticks and tick labels. (In fact, I am happy to do it with only the x-axis tick labels, if it is possible to treat ticks and tick labels separately). An example of this is shown in this image above (which I accomplished with pad=500).
I looked around other threads and in the documentation, but I'm either missing it or don't know the correct terms to find it.
UPDATE: I added gridlines and was getting very unexpected behavior (e.g. linestyle and linewidth didn't work as expected) due to the top x-axis being shifted. I realized yet a better way - keep the axes (turn off the splines) and simply plot a second line at (0, 0) to (max_time, 0).
ax.plot([0,times[-1]], [0,0], color='k') # Creates a 'false' x-axis at y=0
ax.spines['top'].set_color('none') # Position unchanged
ax.spines['bottom'].set_color('none') # Position unchanged
Figured it out! I was thinking about this the wrong way...
Problem: Moving the bottom x-axis to the center and padding the tick labels
Solution: Keep the bottom x-axis where it is (turn off the bottom spine) and move the top x-axis to the center (keep top spine, but turn off ticks and tick labels).
ax.spines['top'].set_position('center')
ax.spines['bottom'].set_color('none') # Position unchanged
ax.xaxis.set_tick_params(top='off')
plt.setp() as in https://matplotlib.org/stable/gallery/images_contours_and_fields/image_annotated_heatmap.html#sphx-glr-gallery-images-contours-and-fields-image-annotated-heatmap-py solved the problem for me.