This question already has answers here:
How to relabel axis ticks for a matplotlib heatmap
(3 answers)
Closed 1 year ago.
I am creating a heatmap in matplotlib where on the x and y axis is some parameter of a measurement and the color represents the value of the measurement. Matplotlib automatically gives the axes ticks based on the index of the value. For example if on the x axis I am measuring at 50 different values the ticks will be from 0 to 50. However the real value of this parameter is for example from -30 to 80 and I would like matplotlib to create the ticks based on this minimum and maximum.
I have tried using set_xticks but this requires the positions of the ticks as well as their labels. I am thinking that I should be able to just give matplotlib a min of -34 and max of 67 and have it create nice looking ticks placed at the proper positions but I haven't been able to find how.
After some digging in examples on the matplotlib website I found this option in imshow called extent in which you can replace the default zero-based coordinates with your own values for the min and max of both axes.
Wouldn't pyplot.xlim() or pyplot.figure.set_xlim() work in this case? Just say something like:
import matplotlib.pyplot as plt
plt.xlim(-30,80)
plt.ylim(0,100) #Or whatever
As far as I know the set_xticks function is too sophisticated for this. With that one you can specify what to put as your tick labels etc. For example if you want to associate a numerical series with a series of letters. For example:
x = [-8,-6,-4,-2,0,2,4,6,8]
labels = ['K2','K4','K6','K8','M0','M2','M4','M6','M8']
plt.xticks(x, labels)
Is one I used personally to translate integers into stellar spectral types (which is relevant, since I'm an astronomer ;p).
Hope this helps.
`
Related
graph
how do I make this graph infill all the square around it? (I colored the part that I want to take off in yellow, for reference)
Normally I use two methods to adjust axis limits depending on a situation.
When a graph is simple, axis.set_ylim(bottom, top) method is a quick way to directly change y-axis (you might know this already).
Another way is to use matplotlib.ticker. It gives you more utilities to adjust axis ticks in your graph.
https://matplotlib.org/3.1.1/gallery/ticks_and_spines/tick-formatters.html
I'm guessing you're using a list of strings to set yaxis tick labels. You may want to set locations (float numbers) and labels (string) of y-axis ticks separatedly. Then set the limits on locations like the following snippet.
import matplotlib.pyplot as plt
import matplotlib.ticker as mt
fig, ax = plt.subplots(1,1)
ax.plot([0,1,2], [0,1,2])
ax.yaxis.set_major_locator(mt.FixedLocator([0,1,2]))
ax.yaxis.set_major_formatter(mt.FixedFormatter(["String1", "String2", "String3"]))
ax.set_ylim(bottom=0, top=2)
It gives you this: generated figure
Try setting the min and max of your x and y axes.
This question already has an answer here:
python matplot.hist - remove gaps between bars
(1 answer)
Closed 4 months ago.
I am plotting some data with
g = seaborn.displot(data, x=var, stat='probability')
# Set appropriate ticks
plt.xticks(np.arange(0, int(data[var].max() + 1), 1.0))
plt.show()
which is giving me the desired plot:
But I would like to compress the axis to remove the unnecessary space and I'm struggling to work out how.
You can increase the margins that determine the space added at both sides of the data limit to get the view limit. Default is 0.05.
plt.margins(x=0.5)
As pointed out by JohanC in the comment below: if your data are discrete values you may specify discrete=True or cast your data to strings to plot them as categories (in the latter case you don't need to set the ticks manually).
sns.displot(data[var].astype(str), stat='probability')
I have a bokeh plot with date on the x-axis (data["obs_date"]) and I want another x-axis at the top covering the same range but shown in a different format (mjd below).
I have tried to add the second axis with:
plot.extra_x_ranges = {"MJD":
Range1d(start=Time(min(data["obs_date"])).mjd,
end=Time(max(data["obs_date"])).mjd)}
plot.add_layout(LinearAxis(x_range_name="MJD", axis_label="MJD",
axis_label_text_font_size="16pt"),
"above")
However, because bokeh adds a small buffer to the limits of the plot, using min max of data["obs_date"] as the limits for this new axis gives me a small offset - in the image below 16 Jan 2018 should align with 58134. It also causes it to break when I only have one point to plot.
How can I set the limits of my new axis so that it is 'aware' of the limits of the primary axis? Coming form a matplotlib background, I suppose the equivalent I am looking for is ax.get_xlim().
Bokeh implicitly uses DataRange1d that computes the padded bounds based on its range_padding, range_padding_units, and follow_interval fields, and whether the underlying scale is linear or logarithmic. But it does not store the computed values.
So, your only options at this point are either to set the boundaries explicitly for both ranges or to compute the boundaries for the extra range based on the aforementioned DataRange1d fields and the scale type.
I am trying to plot a data and function with matplotlib 2.0 under python 2.7.
The x values of the function are evolving with time and the x is first decreasing to a certain value, than increasing again.
If the function is plotted against time, it shows function like this plot of data against time
I need the same x axis evolution for plotting against real x values. Unfortunately as the x values are the same for both parts before and after, both values are mixed together. This gives me the wrong data plot:
In this example it means I need the x-axis to start on value 2.4 and decrease to 1.0 than again increase to 2.4. I swear I found before that this is possible, but unfortunately I can't find a trace about that again.
A matplotlib axis is by default linearly increasing. More importantly, there must be an injective mapping of the number line to the axis units. So changing the data range is not really an option (at least when the aim is to keep things simple).
It would hence be good to keep the original numbers and only change the ticks and ticklabels on the axis. E.g. you could use a FuncFormatter to map the original numbers to
np.abs(x-tp)+tp
where tp would be the turning point.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker
x = np.linspace(-10,20,151)
y = np.exp(-(x-5)**2/19.)
plt.plot(x,y)
tp = 5
fmt = lambda x,pos:"{:g}".format(np.abs(x-tp)+tp)
plt.gca().xaxis.set_major_formatter(matplotlib.ticker.FuncFormatter(fmt))
plt.show()
One option would be to use two axes, and plot your two timespans separately on each axes.
for instance, if you have the following data:
myX = np.linspace(1,2.4,100)
myY1 = -1*myX
myY2 = -0.5*myX-0.5
plt.plot(myX,myY, c='b')
plt.plot(myX,myY2, c='g')
you can instead create two subplots with a shared y-axis and no space between the two axes, plot each time span independently, and finally, adjust the limits of one of your x-axis to reverse the order of the points
fig, (ax1,ax2) = plt.subplots(1,2, gridspec_kw={'wspace':0}, sharey=True)
ax1.plot(myX,myY1, c='b')
ax2.plot(myX,myY2, c='g')
ax1.set_xlim((2.4,1))
ax2.set_xlim((1,2.4))
It's easier to ask this with a figure. At the moment i obtain the following boxplot graph using matplotlib:
Is there a way to obtain a figure like that, but with each box in a position coherent with the corresponding x-axis number (like in a normal scatter plot, but with boxes instead of points)?
At the moment the numbers on the x-axis are added by means of the labels= argument.
You need to specify the positions argument to the boxplot constructor.
from matplotlib import pyplot as plt
plt.boxplot([[1,4],[2,5],[3,6]], positions=[2,4,5.5])
By default it uses the values [1, 2, ..., n] but you can specify a different x position for each bar and the xticks will be updated automatically.