I have a simple plot code as
plt.plot(x,y)
plt.show()
I want to add some extra ticks on the x-axis in addition to the current ones, let's say at
extraticks=[2.1, 3, 7.6]
As you see I do not have a pattern for ticks so I do not want to increase the tick frequency for the whole axis; just keep the original ones and add those extras...
Is it possible, at all?
Regards
Yes, you can try something like:
plt.xticks(list(plt.xticks()[0]) + extraticks)
The function to use is xticks(). When called without arguments, it returns the current ticks. Calling it with arguments, you can set the tick positions and, optionally, labels.
For the sake of completeness, I would like to give the OO version of #Lev-Levitsky's great answer:
lines = plt.plot(x,y)
ax = lines[0].axes
ax.set_xticks(list(ax.get_xticks()) + extraticks)
Here we use the Axes object extracted from the Lines2D sequence returned by plot. Normally if you are using the OO interface you would already have a reference to the Axes up front and you would call plot on that instead of on pyplot.
Corner Caveat
If for some reason you have modified your axis limits (e.g, by programatically zooming in to a portion of the data), you will need to restore them after this operation:
lim = ax.get_xlim()
ax.set_xticks(list(ax.get_xticks()) + extraticks)
ax.set_xlim(lim)
Otherwise, the plot will make the x-axis show all the available ticks on the axis.
Related
Let's look at a swarmplot, made with Python 3.5 and Seaborn on some data (which is stored in a pandas dataframe df with column lables stored in another class. This does not matter for now, just look at the plot):
ax = sns.swarmplot(x=self.dte.label_temperature, y=self.dte.label_current, hue=self.dte.label_voltage, data = df)
Now the data is more readable if plotted in log scale on the y-axis because it goes over some decades.
So let's change the scaling to logarithmic:
ax.set_yscale("log")
ax.set_ylim(bottom = 5*10**-10)
Well I have a problem with the gaps in the swarms. I guess they are there because they have been there when the plot is created with a linear axis in mind and the dots should not overlap there. But now they look kind of strange and there is enough space to from 4 equal looking swarms.
My question is: How can I force seaborn to recalculate the position of the dots to create better looking swarms?
mwaskom hinted to me in the comments how to solve this.
It is even stated in the swamplot doku:
Note that arranging the points properly requires an accurate transformation between data and point coordinates. This means that non-default axis limits should be set before drawing the swarm plot.
Setting an existing axis to log-scale and use this for the plot:
fig = plt.figure() # create figure
rect = 0,0,1,1 # create an rectangle for the new axis
log_ax = fig.add_axes(rect) # create a new axis (or use an existing one)
log_ax.set_yscale("log") # log first
sns.swarmplot(x=self.dte.label_temperature, y=self.dte.label_current, hue=self.dte.label_voltage, data = df, ax = log_ax)
This yields in the correct and desired plotting behaviour:
I have a plot look like this:
Obviously, the left and right side is a waste of space, so I set
plt.axis('tight')
But this gives me plot like this:
The xlim looks right now, but the ylim is too tight for the plot.
I'm wondering, if I can only set axis(tight) only to x axis in my case?
So the plot may look something like this:
It's certainly possible that I can do this manually by
plt.gca().set_xlim(left=-10, right=360)
But I'm afraid this is not a very elegant solution.
You want to use matplotlib's autoscale method from the matplotlib.axes.Axes class.
Using the functional API, you apply a tight x axis using
plt.autoscale(enable=True, axis='x', tight=True)
or if you are using the object oriented API you would use
ax = plt.gca() # only to illustrate what `ax` is
ax.autoscale(enable=True, axis='x', tight=True)
For completeness, the axis kwarg can take 'x', 'y', or 'both', where the default is 'both'.
I just put the following at the beginning of those scripts in which I know I'll want my xlims to hug my data:
import matplotlib.pyplot as plt
plt.rcParams['axes.xmargin'] = 0
If I decide to add some whitespace buffer to an individual plot in that same script, I do it manually with:
plt.xlim(lower_limit, upper_limit)
While the accepted answer works, and is what I used for a while, I switched to this strategy because I only have to remember it once per script.
I would like to remove the numerical values in each thick of my y-axis (10, 20, 30, etc.) but keeping the thick marks and the axis label.
So far I just have:
yticks([])
but it removes the ticks as well. I also tried:
frame=gca()
frame.axes.get_yaxis().set_visible(False)
but it removes both axis label and axis ticks.
I agree with Mathieu that tick_params() is a better method (because you don't need to know the number of ticks in advance), however the most generalized parameter is "label1On," i.e.:
gca().tick_params(axis='x',label1On=False)
This approach easily extends to 'y' axis, as well as the second 'x' or 'y' axes (using label2On).
The tick_params() function should do the job:
gca().tick_params(axis='x',labelbottom='off')
You can set the tick labels to an empty list:
from matplotlib.pyplot import *
gca().set_xticklabels(['']*10)
plot(range(10))
Results in
I had to do that before I called plot. Not sure why the other way around didn't work
How can I prevent the labels of xticks from overlapping with the labels of yticks when using hist (or other plotting commands) in matplotlib?
There are several ways.
One is to use the tight_layout method of the figure you are drawing, which will automatically try to optimize the appareance of the labels.
fig, ax = subplots(1)
ax.plot(arange(10),rand(10))
fig.tight_layout()
An other way is to modify the rcParams values for the ticks formatting:
rcParams['xtick.major.pad'] = 6
This will draw the ticks a little farter from the axes. after modifying the rcparams (this of any other, you can find the complete list on your matplotlibrc configuration file), remember to set it back to deafult with the rcdefaults function.
A third way is to tamper with the axes locator_params telling it to not draw the label in the corner:
fig, ax = subplots(1)
ax.plot(arange(10),rand(10))
ax.locator_params(prune='lower',axis='both')
the axis keywords tell the locator on which axis it should work and the prune keyword tell it to remove the lowest value of the tick
Try increasing the padding between the ticks on the labels
import matplotlib
matplotlib.rcParams['xtick.major.pad'] = 8 # defaults are 4
matplotlib.rcParams['ytick.major.pad'] = 8
same goes for [x|y]tick.minor.pad.
Also, try setting: [x|y]tick.direction to 'out'. That gives you a little more room and helps makes the ticks a little more visible -- especially on histograms with dark bars.
I would like to draw a standard 2D line graph with pylot, but force the axes' values to be between 0 and 600 on the x, and 10k and 20k on the y. Let me go with an example...
import pylab as p
p.title(save_file)
p.axis([0.0,600.0,1000000.0,2000000.0])
#define keys and items elsewhere..
p.plot(keys,items)
p.savefig(save_file, dpi=100)
However, the axes still adjust to the size of the data. I'm interpreting the effect of p.axis to be setting what the max and min could be, not enforcing them to be the max or min. The same happens when I try to use p.xlim() etc.
Any thoughts?
Thanks.
Calling p.plot after setting the limits is why it is rescaling. You are correct in that turning autoscaling off will get the right answer, but so will calling xlim() or ylim() after your plot command.
I use this quite a lot to invert the x axis, I work in astronomy and we use a magnitude system which is backwards (ie. brighter stars have a smaller magnitude) so I usually swap the limits with
lims = xlim()
xlim([lims[1], lims[0]])
To answer my own question, the trick is to turn auto scaling off...
p.axis([0.0,600.0, 10000.0,20000.0])
ax = p.gca()
ax.set_autoscale_on(False)
I tried all of those above answers, and I then summarized a pipeline of how to draw the fixed-axes image. It applied both to show function and savefig function.
before you plot:
fig = pylab.figure()
ax = fig.gca()
ax.set_autoscale_on(False)
This is to request an ax which is subplot(1,1,1).
During the plot:
ax.plot('You plot argument') # Put inside your argument, like ax.plot(x,y,label='test')
ax.axis('The list of range') # Put in side your range [xmin,xmax,ymin,ymax], like ax.axis([-5,5,-5,200])
After the plot:
To show the image :
fig.show()
To save the figure :
fig.savefig('the name of your figure')
I find out that put axis at the front of the code won't work even though I have set autoscale_on to False.
I used this code to create a series of animation. And below is the example of combing multiple fixed axes images into an animation.
Try putting the call to axis after all plotting commands.