By default, when I add axes to an image in matplotlib, the x axis begins at 0 and increases from left to right and the y-axis begins at 0, increasing from bottom to top. I would like to have the y-axis beginning at zero, but from top to bottom (that is, 0 on the top, and the maximum value on the bottom) How could I accomplish this?
If I understand correctly, you're asking how to reverse the y-axis. This can be done with
plt.gca().invert_yaxis()
which takes the current axis plt.gca() and calls its method invert_yaxis() to invert the y-axis.
You can also simply call plt.ylim() and put the coordinates in reverse order. I know I always fine-tune the range of all plots by hand anyway, so this is easier in that situation. So let's say you have a plot that runs from 0 to 10, you would just call
plt.ylim(10,0)
and it will flip the y-axis.
Related
[![example showing overlapping problem][1]][1]
[1]: https://i.stack.imgur.com/cL3Q3.png
using plot from matplotlib with many subplots, the y-axis ticks' text overlaps with the next subplot to the left. It's always exponential (scientific) with e.g. '1e7' on top and '1.5' at the tick mark. Sometimes there is no '.5' and just '1' at the tick mark, then there is no overlapping. So I want to enforce a format with only the leading digit. I even have found a solution for that:
def MyFormatter(x,lim):
if x == 0:
return 0
return '{0:.0f}'.format(np.sign(x)*10**(-np.floor(np.log10(abs(x)))+np.log10(abs(x))))
majorFormatter = FuncFormatter(MyFormatter)
But using that (or anything else) as set_major_formatter(majorFormatter) the '1e7' on top is removed. How would I solve that?
TL;DR: How can I get a subrange of a violinplot whilst keeping accurate quartile lines?
I am using seaborn violinplots to make static charts for a report, but as far as I can tell, there's no way to redraw a particular area between limits whilst retaining the 25/median/75 quartile lines of the original dataset.
Here's my example dataset as a violin. The 25/median/75 values are left side: 1.0/5.0/9.0; right side: 2.0/5.0/9.0
My data has such a long tail that all the useful info is scrunched up into a tiny area. I want to ignore (but not throw away) the tail and show a closer look at the interesting bit.
I tried to reset the ylim using ax.set(ylim=(0, upp)), but the resultant graph is not great: it's jaggy and the inner lines don't meet the violin edge.
Is there a way to reset the y-axis limits but get a better quality result?
Next I tried to cut off the tail by dropping values from the dataset. I dropped anything over the 97th centile. The violin looks way better, but the quartile lines have been recalculated for this new dataset. They're showing a median of about 4, not 5 as per the original dataset.
I'm using inner="quartile", so the code that gets called in Seaborn is _ViolinPlotter::draw_quartiles
def draw_quartiles(self, ax, data, support, density, center, split=False):
"""Draw the quartiles as lines at width of density."""
q25, q50, q75 = np.percentile(data, [25, 50, 75])
self.draw_to_density(ax, center, q25, support, density, split,
linewidth=self.linewidth,
dashes=[self.linewidth * 1.5] * 2)
As you can see, it assumes (understandably) that one wants to draw the quartile lines at percentiles 25, 50 and 75. It'd be amazeballs if there was a way I could call draw_to_density with my own values (is there?).
At the moment, I am attempting to manually adjust the position of the lines. It's trivial to figure out & set the y-values:
for l in ax.lines:
l.set_ydata(<get correct quartile value from original dataset>)
but I'm finding it hard to figure out the limits for x, i.e. the density of the distribution at the quartiles. It seems to involve gaussian kde, and tbh it's getting hacky and inelegant at this point. Is there an easy way to calculate how long each line should be?
What do you suggest?
Thanks for your help
Lnr
W/ Thanks to #JohanC.
added gridsize=1000 to the params of the violinplot and used ax.set(ylim=(0, upp)) to resize the y-axis to show the range from 0 to upp where upp is the upper limit. Much prettier lookin' graph:
Is there a way to render the tick labels just right inside the axes, i.e, something like the direction property there is on the ticks themself?
Right now I'm setting the x property to a positive value on the ticklabels to draw them inside of the axis, i.e.,
ax2.set_yticklabels(['0', '2500', '5000', '7500'], minor=False, x=0.05)
But this doesn't really work on resizable plots, as the 0.05 figure is absolute (and too big on big plots).
Any ideas?
I'm assuming that ax2 is constructed as ax2 = ax.twinx(), which is to say that it is on the right side of the axes.
You could do something like the following:
ax2.set_yticklabels(['0', '2500', '5000', '7500'], minor=False, horizontalalignment='right')
for tick in ax2.yaxis.get_major_ticks():
tick.set_pad(-8)
If you want the left side axis on the inside too, then you'd simply switch the horizontal alignment to 'left' and change the pad from -8 to -25.
The two numbers might not be exact and could depend on other matplotlib settings you might have (e.g. length of major ticks) so you may want to increase or decrease those values slightly.
I'd like to have one axis label centered over two axes in matplotlib.
For example, I set up the axes as follows:
figure = pyplot.figure(figsize=10,10))
diagram1 = figure.add_axes([0.01,0.62,0.90,0.30])
diagram2 = figure.add_axes([0.01,0.32,0.90,0.30])
This will generate two diagrams on top of each other. How can i now define one axis label for the y axis centered on both diagrams.
I think this can be done with subplots, but I prefer to set every diagram individually, as shown above.
You can manually change the y-coordinate of the label.
diagram1.set_ylabel('y label').set_y(0)
# Alternatively you can use
# diagram2.set_ylabel('y label').set_y(1)
The coordinate is in the axes coordinate space, meaning 0 is the bottom and 1 is the top of the Axes.
Seeing how your Axes are placed at x=0.01, you can make the label appear at the right side of the plots as well
diagram1.yaxis.set_label_position("right")
I am trying to plot a matrix in Gnuplot as I would using imshow in Matplotlib. That means I just want to plot the actual matrix values, not the interpolation between values. I have been able to do this by trying
splot "file.dat" u 1:2:3 ps 5 pt 5 palette
This way we are telling the program to use columns 1,2 and 3 in the file, use squares of size 5 and space the points with very narrow gaps. However the points in my dataset are not evenly spaced and hence I get discontinuities.
Anyone a method of plotting matrix values in gnuplot regardless of not evenly spaced in Xa and y axes?
Gnuplot doesn't need to have evenly space X and Y axes. ( see another one of my answers: https://stackoverflow.com/a/10690041/748858 ). I frequently deal with grids that look like x[i] = f_x(i) and y[j] = f_y(j). This is quite trivial to plot, the datafile just looks like:
#datafile.dat
x1 y1 z11
x1 y2 z12
...
x1 yN z1N
#<--- blank line (leave these comments out of your datafile ;)
x2 y1 z21
x2 y2 z22
...
x2 yN z2N
#<--- blank line
...
...
#<--- blank line
xN y1 zN1
...
xN yN zNN
(note the blank lines)
A datafile like that can be plotted as:
set view map
splot "datafile.dat" u 1:2:3 w pm3d
the option set pm3d corners2color can be used to fine tune which corner you want to color the rectangle created.
Also note that you could make essentially the same plot doing this:
set view map
plot "datafile.dat" u 1:2:3 w image
Although I don't use this one myself, so it might fail with a non-equally spaced rectangular grid (you'll need to try it).
Response to your comment
Yes, pm3d does generate (M-1)x(N-1) quadrilaterals as you've alluded to in your comment -- It takes the 4 corners and (by default) averages their value to assign a color. You seem to dislike this -- although (in most cases) I doubt you'd be able to tell a difference in the plot for reasonably large M and N (larger than 20). So, before we go on, you may want to ask yourself if it is really necessary to plot EVERY POINT.
That being said, with a little work, gnuplot can still do what you want. The solution is to specify that a particular corner is to be used to assign the color to the entire quadrilateral.
#specify that the first corner should be used for coloring the quadrilateral
set pm3d corners2color c1 #could also be c2,c3, or c4.
Then simply append the last row and last column of your matrix to plot it twice (making up an extra gridpoint to accommodate the larger dataset. You're not quite there yet, you still need to shift your grid values by half a cell so that your quadrilaterals are centered on the point in question -- which way you shift the cells depends on your choice of corner (c1,c2,c3,c4) -- You'll need to play around with it to figure out which one you want.
Note that the problem here isn't gnuplot. It's that there isn't enough information in the datafile to construct an MxN surface given MxN triples. At each point, you need to know it's position (x,y) it's value (z) and also the size of the quadrilateral to be draw there -- which is more information than you've packed into the file. Of course, you can guess the size in the interior points (just meet halfway), but there's no guessing on the exterior points. but why not just use the size of the next interior point?. That's a good question, and it would (typically) work well for rectangular grids, but that is only a special case (although a common one) -- which would (likely) fail miserably for many other grids. The point is that gnuplot decided that averaging the corners is typically "close enough", but then gives you the option to change it.
See the explanation for the input data here. You may have to change your data file's format accordingly.