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")
Related
I want to create a figure that shows a background image with overlaid scatter and line plots:
As you can see, the axes ticks show image coordinates. The scatter and line plot are given in image coordinates, too - which is not desired. The scatter and line plots should still be able to work (and be meaningful) without the background image. The extent is not known because this figure is used to determine the extent (interactively) in the first place.
Instead, I'd like to specify the scatter and line plots in the coordinate system shown in the background image (units m³/h and m): the transformation from image coordinates to "axis on top" coordinates would be roughly (110,475) -> (0,10) and (530,190) -> (8,40).
In principle I can see two ways of doing it:
specify image extent after it has been added. However, I don't see this documented anywhere; This example shows how it's done when the extent is known at the call to imshow(): Plot over an image background in python
add an axes on top of the image axes with twinx and twin y, where both x,x and y,y pairs are tightly coupled. I have only seen features that allow me to specify a shared x or a shared y axis, not both.
The restriction here seems to be that "The scatter and line plots should still be able to work (and be meaningful) without the background image.". This however would not imply that you cannot use the extent keyword argument.
At the time you add the image, you'd specify the extent.
plt.scatter(...)
plt.plot(...)
plt.imshow(..., extent = [...])
You can also set the extent later, if that is desired for some reason not explained in the question, i.e.
plt.scatter(...)
plt.plot(...)
im = plt.imshow(...)
im.set_extent([...])
Finally you may also decide to remove the image, and plot it again; this time with the desired extent,
plt.scatter(...)
plt.plot(...)
im = plt.imshow(...)
im.remove()
im = plt.imshow(..., extent=[...])
I'm using a dark theme on Jupyter Notebook and I find that when I make a plot using matplotlib, the plot looks like this:
So it is very hard to read the tick labels, as it seems that although the plot background is white, the background in this part is transparent.
I'm aware that this can be fixed on a plot by plot basis by using the following lines of code:
fig = plt.figure()
fig.patch.set_facecolor('white')
sns.scatterplot(train.X, train.y)
But is there a way to set a global property of matplotlib so that I don't need to do this each time?
Easiest I can think of:
sns.set()
sns.scatterplot(df.x,df.y)
Output:
I have an (as yet incomplete) image of the whole sky. In order to display it properly it needs to be projected onto an ellipse (specifically an Aitoff projection).
I have tried various versions of this:
plt.subplot(111, projection="aitoff")
plt.imshow(image, vmin=0.004, vmax=0.01, extent=[0,360,-90,90])
plt.show()
...and have tried changing the values in the extent kwarg to radians, as well as using pcolor or pcolormesh instead of imshow.
These have given me: an empty Aitoff plot, various Aitoff plots with all or part of my image sitting inside it, but not filling it, or an Aitoff plot with a small part of my image (one or two pixels by the looks of things) completely filling it.
My whole image sitting within a plot
The unprojected image
I also do not have access to things like Basemap or astroproj as I'm using a machine owned by my university.
Edit: As was pointed out by another user the above example is not Minimal, Complete, and Verifiable. Below is a version which should be:
A=np.random.rand(180,360)
plt.imshow(A)
plt.show()
plt.subplot(111, projection="aitoff")
plt.pcolormesh(A)
plt.show()
I want the entire image generated in the plt.imshow() command to be projected in the Aitoff figure. Instead only a few pixels are. Any ideas?
Thanks!
Using imshow in non-rectilinear projections will mostly fail. But instead pcolormesh may be used.
The aitoff projection ranges from -π to π in horizontal and from -π/2 to π/2 in vertical direction. This is the range of values to use when plotting the pcolormesh plot.
import numpy as np
import matplotlib.pyplot as plt
im = plt.imread("house.jpg")
x = np.linspace(-np.pi,np.pi,im.shape[1])
y = np.linspace(-np.pi/2,np.pi/2,im.shape[0])
X,Y = np.meshgrid(x,y)
plt.subplot(111, projection="aitoff")
plt.pcolormesh(X,Y[::-1],im[:,:,2])
plt.show()
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.
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.