Matplotlib arrow in loglog plot - python

I'm trying to draw an arrow into a loglog plot with matplotlib, which looks like this:
I know that it has been suggested to turn off the axis (Matplotlib: Draw a vertical arrow in a log-log plot), but I do need the axes. In addition, the suggestion did not seem to change anything (apart from turning the axes off, as expected):
plt.figure();plt.loglog([1,10,60],[1,0.1,0.005])
plt.axis('off')
plt.arrow(2,0.002,5,0.098,'k',head_length=0.3)
My work around so far has been to create an invisible inset (meaning: axes off) with a linear axes environment and plot the arrow in the inset, which works but is really a bit unpleasant. Is there a simpler way? Or do people recommend to add these type of additional features with eg. inkscape, after the main plot is done?

You can use plt.annotate rather than plt.arrow. This is noted in the documentation for plt.arrow:
The resulting arrow is affected by the axes aspect ratio and limits.
This may produce an arrow whose head is not square with its stem. To
create an arrow whose head is square with its stem, use annotate()
For example:
import matplotlib.pyplot as plt
plt.figure()
plt.loglog([1,10,60],[1,0.1,0.005])
plt.annotate('', xy=(5, 0.098), xytext=(2, 0.002),
arrowprops=dict(facecolor='black', shrink=0.),
)
plt.ylim(0.001, 10)
plt.show()
Note that you may need to adjust the axes limits to fit the arrow into the plot. Here I had to change ylim.

Related

Jupyter-notebook non-transparent plot surroundings when saving figure

I am using jupyter-lab for plotting a dataframe.
fig = df.plot().get_figure()
fig.savefig("test.png")
Unfortunately, the surroundings of the plot (the space that is not between the x and y axis), where the coordinates are displayed are transparent, meaning a checkered grey-black pattern, which makes the coordinates practically unreadable. Is there any way of widening the non-transparent area so that the coordinates are included?
There are a couple of ways that you can achieve this:
Update the matplotlib rcParams:
import matplotlib as mpl
mpl.rcParams.update({"figure.facecolor": "white"})
this will affect all the plots after you set this parameter in this script.
Set the figure facecolor for a single figure:
fig = df.plot().get_figure()
fig.set_facecolor("white")

How to draw scale-independent arrows with matplotlib

I have drawn a trajectory plot in python using matplotlib of a boat like so:
Now I want to add some arrows, like wind direction, true heading etc. However I want the arrows to have the same size no matter which zoom-level the plot is at. I tried matplotlib.pyplot.arrow, however there I have to define the length of the arrows. I could make matplotlib.pyplot.arrow work, but then I'd have to get the height and width of the plot, and scale my arrows accordingly, so I wondered if there was a better way to obtain scale-independent arrows for these points?
You want to use matplotlib.axes.Axes.annotate instead. See the docs for more info!
Basically, set the xycoords parameter to "axes fraction" to instruct it to plot using relative fraction of the axes itself rather than data coordinates.

creating a chart with high/low and percentile box plus other points

Hi I'd like to recreate the following plot with matplotlib and pandas.
I started to use boxplot but i'm struggling to manipulate the kwargs.
Is there a simple way to use boxplot or do I need to recreate the chart enitrely.
One issue I had was also adding the current data?
Best regards
The boxplot from matplotlib has indeed some limitations. For you to have full control over how the plot looks I would advise using Patches to draw Rectangles for example (code from Rectangles link):
import matplotlib.pyplot as plt
import matplotlib.patches as patches
fig1 = plt.figure()
ax1 = fig1.add_subplot(111, aspect='equal')
ax1.add_patch(
patches.Rectangle(
(0.1, 0.1), # (x,y)
0.5, # width
0.5, # height
)
)
fig1.savefig('rect1.png', dpi=90, bbox_inches='tight')
This is useful because you'll only need this and a normal plot command (for lines) in matplotlib to do a boxplot. This will give you immense control about color and shape and it's fairly easy to build. You also have text there you'll need for which you can use matplotlib text. The last thing are those markers which are very doable with a scatter.
A boxplot is a shape that tells you information such a minimum, maximum, and percentiles (25,50,75). You can calculate this very easily with numpy percentile.
The details of the plot (labels at the bottom, legend, title in box, and so on) can also be achieved but tinkering with labels, manually building a title box and so on.
It will give you some work but these are the commands you need.

Python/Matplotlib: How to plot in a subplot with ticks but no tick labels?

I can remove the tick labels with:
ax.axes.get_yaxis().set_visible(False)
But that removes the ticks as well. I want to preserve the ticks.
Just use a NullFormatter
ax = plt.gca()
ax.yaxis.set_major_formatter(matplotlib.ticker.NullFormatter())
plt.draw()
+1 for #tcaswell answer, I guess that's the standard way to do so. But it has the drawback that the formatter is now missing, and when you move the mouse on your plot you do not get the coordinates of the point the mouse is pointing to.
This is a nice feature I usually rely on, especially because the "data cursor" tool (link) present in Matlab is missing in Matplotlib by default (see mpldatacursor for a plugin with similar features). In Matplotlib I use to hover on a point with the mouse, and read the 'live' coordinates provided by the Formatter.
To turn off the labels without killing the formatter you can use
plt.setp(ax.get_yticklabels(), visible=False)

How do I let my matplotlib plot go beyond the axes?

I have to translate an image plotting script from matlab to matplotlib/pylab, and I'm trying to achieve the same effect as the matlab image below:
As you can see, the z order of the plots seem to be higher than the z order of the grid, so the markers are not hidden by the axes. However, I can't figure out a way to do the same with my matplotlib image:
I'm wondering if it is possible to get the same display without having to increase the limits of the y axis.
To get the marker to show beyond the axes you can turn the clipping off. This can be done using the keyword argument in the plot command clip_on=False.
For example:
import matplotlib.pyplot as plt
plt.plot(range(5), range(5), 'ro', markersize=20, clip_on=False, zorder=100)
plt.show()
This is a complete example of how to use the zorder kwarg: http://matplotlib.sourceforge.net/examples/pylab_examples/zorder_demo.html
Note that a higher z-order equates to a graph-element being more in the foreground.
For your second question, have a look at the figsize kwarg to instances of the Figure class: http://matplotlib.sourceforge.net/api/figure_api.html?highlight=figsize#matplotlib.figure.Figure
If you run into issues, please post some of your code and we'll be able to give more-detailed recommendations. Best of luck.
If you're plotting the lines one after the other, just change the order of the plotting calls and that would fix the z order.

Categories

Resources