Using Pandas to plot in I-Python Notebook, I have several plots and because Matplotlib decides the Y axis it is setting them differently and we need to compare that data using the same range.
I have tried several variants on: (I assume I'll need to apply the limits to each plot.. but since I can't get one working... From the Matplotlib doc it seems that I need to set ylim, but can't figure the syntax to do so.
df2250.plot(); plt.ylim((100000,500000)) <<<< if I insert the ; I get int not callable and if I leave it out I get invalid syntax. anyhow, neither is right...
df2260.plot()
df5.plot()
I'm guessing this was a feature added after this answer was accepted in 2013; DataFrame.plot() now exposes a ylim parameter that sets the y axis limits:
df.plot(ylim=(0,200))
See pandas documentation for details.
Pandas plot() returns the axes, you can use it to set the ylim on it.
ax1 = df2250.plot()
ax2 = df2260.plot()
ax3 = df5.plot()
ax1.set_ylim(100000,500000)
ax2.set_ylim(100000,500000)
etc...
You can also pass an axes to Pandas plot, so plotting it in the same axes can be done like:
ax1 = df2250.plot()
df2260.plot(ax=ax1)
etc...
If you want a lot of different plots, defining the axes beforehand and within one figure might be the solution that gives you the most control:
fig, axs = plt.subplots(1,3,figsize=(10,4), subplot_kw={'ylim': (100000,500000)})
df2260.plot(ax=axs[0])
df2260.plot(ax=axs[1])
etc...
Related
In Matplotlib, I make dashed grid lines as follows:
fig = pylab.figure()
ax = fig.add_subplot(1,1,1)
ax.yaxis.grid(color='gray', linestyle='dashed')
however, I can't find out how (or even if it is possible) to make the grid lines be drawn behind other graph elements, such as bars. Changing the order of adding the grid versus adding other elements makes no difference.
Is it possible to make it so that the grid lines appear behind everything else?
According to this - http://matplotlib.1069221.n5.nabble.com/axis-elements-and-zorder-td5346.html - you can use Axis.set_axisbelow(True)
(I am currently installing matplotlib for the first time, so have no idea if that's correct - I just found it by googling "matplotlib z order grid" - "z order" is typically used to describe this kind of thing (z being the axis "out of the page"))
To me, it was unclear how to apply andrew cooke's answer, so this is a complete solution based on that:
ax.set_axisbelow(True)
ax.yaxis.grid(color='gray', linestyle='dashed')
If you want to validate the setting for all figures, you may set
plt.rc('axes', axisbelow=True)
or
plt.rcParams['axes.axisbelow'] = True
It works for Matplotlib>=2.0.
I had the same problem and the following worked:
[line.set_zorder(3) for line in ax.lines]
fig.show() # to update
Increase 3to a higher value if it does not work.
You can also set the zorder kwarg in matplotlib.pyplot.grid
plt.grid(which='major', axis='y', zorder=-1.0)
You can try to use one of Seaborn's styles. For instance:
import seaborn as sns
sns.set_style("whitegrid")
Not only the gridlines will get behind but the looks are nicer.
For some (like me) it might be interesting to draw the grid behind only "some" of the other elements. For granular control of the draw order, you can use matplotlib.artist.Artist.set_zorder on the axes directly:
ax.yaxis.grid(color='gray', linestyle='dashed')
ax.set_zorder(3)
This is mentioned in the notes on matplotlib.axes.Axes.grid.
I'm getting a bit confused around the concepts of axes, and frankly - what modifies what when it comes to the matplotlib backend. I was told in this post that "whenever you first do something that requires an axes object, one is created for you and becomes the default object that all of your future actions will be applied to until you change the current axes to something else."
But why is it, then, that figsize doesn't seem to do anything when I use the following code in the same cells in a Jupyter notebook:
dataset[['TV','radio']].plot()
plt.figure(figsize=(5,10))
and also
dataset.hist()
plt.figure(figsize=(10,20))
Why don't either of these work? How can I tell which axes object I'm referencing? Thanks so much
The problem is that plt.figure creates a new figure.
If you want to resize the existing figure use this:
dataset[['TV','radio']].plot()
fig = plt.gcf() # gcf: get current figure
fig.set_size_inches(5,10)
Another way you could do it -- that's illustrative of how axes get created and later used -- is to start off with the figure size like this:
import numpy as np, pandas as pd
df = pd.DataFrame({'x':[np.random.randint(0,10) for i in range(10)]})
fig = plt.figure(figsize=(5,5))
ax = fig.gca() # gca: get current axes
df.plot(ax=ax)
Result:
Updated MRE with subplots
I'm not sure of the usefulness of the original question and MRE. The margin padding seems to be properly adjusted for large x and y labels.
The issue is reproducible with subplots.
Using matplotlib 3.4.2
fig, axes = plt.subplots(ncols=2, nrows=2, figsize=(8, 6))
axes = axes.flatten()
for ax in axes:
ax.set_ylabel(r'$\ln\left(\frac{x_a-x_b}{x_a-x_c}\right)$')
ax.set_xlabel(r'$\ln\left(\frac{x_a-x_d}{x_a-x_e}\right)$')
plt.show()
Original
I am plotting a dataset using matplotlib where I have an xlabel that is quite "tall" (it's a formula rendered in TeX that contains a fraction and is therefore has the height equivalent of a couple of lines of text).
In any case, the bottom of the formula is always cut off when I draw the figures. Changing figure size doesn't seem to help this, and I haven't been able to figure out how to shift the x-axis "up" to make room for the xlabel. Something like that would be a reasonable temporary solution, but what would be nice would be to have a way to make matplotlib recognize automatically that the label is cut off and resize accordingly.
Here's an example of what I mean:
import matplotlib.pyplot as plt
plt.figure()
plt.ylabel(r'$\ln\left(\frac{x_a-x_b}{x_a-x_c}\right)$')
plt.xlabel(r'$\ln\left(\frac{x_a-x_d}{x_a-x_e}\right)$', fontsize=50)
plt.title('Example with matplotlib 3.4.2\nMRE no longer an issue')
plt.show()
The entire ylabel is visible, however, the xlabel is cut off at the bottom.
In the case this is a machine-specific problem, I am running this on OSX 10.6.8 with matplotlib 1.0.0
Use:
import matplotlib.pyplot as plt
plt.gcf().subplots_adjust(bottom=0.15)
# alternate option without .gcf
plt.subplots_adjust(bottom=0.15)
to make room for the label, where plt.gcf() means get the current figure. plt.gca(), which gets the current Axes, can also be used.
Edit:
Since I gave the answer, matplotlib has added the plt.tight_layout() function.
See matplotlib Tutorials: Tight Layout Guide
So I suggest using it:
fig, axes = plt.subplots(ncols=2, nrows=2, figsize=(8, 6))
axes = axes.flatten()
for ax in axes:
ax.set_ylabel(r'$\ln\left(\frac{x_a-x_b}{x_a-x_c}\right)$')
ax.set_xlabel(r'$\ln\left(\frac{x_a-x_d}{x_a-x_e}\right)$')
plt.tight_layout()
plt.show()
In case you want to store it to a file, you solve it using bbox_inches="tight" argument:
plt.savefig('myfile.png', bbox_inches="tight")
An easy option is to configure matplotlib to automatically adjust the plot size. It works perfectly for me and I'm not sure why it's not activated by default.
Method 1
Set this in your matplotlibrc file
figure.autolayout : True
See here for more information on customizing the matplotlibrc file: http://matplotlib.org/users/customizing.html
Method 2
Update the rcParams during runtime like this
from matplotlib import rcParams
rcParams.update({'figure.autolayout': True})
The advantage of using this approach is that your code will produce the same graphs on differently-configured machines.
plt.autoscale() worked for me.
You can also set custom padding as defaults in your $HOME/.matplotlib/matplotlib_rc as follows. In the example below I have modified both the bottom and left out-of-the-box padding:
# The figure subplot parameters. All dimensions are a fraction of the
# figure width or height
figure.subplot.left : 0.1 #left side of the subplots of the figure
#figure.subplot.right : 0.9
figure.subplot.bottom : 0.15
...
There is also a way to do this using the OOP interface, applying tight_layout directly to a figure:
fig, ax = plt.subplots()
fig.set_tight_layout(True)
https://matplotlib.org/stable/api/figure_api.html
for some reason sharex was set to True so I turned it back to False and it worked fine.
df.plot(........,sharex=False)
You need to use sizzors to modify the axis-range:
import sizzors as sizzors_module
sizzors_module.reshape_the_axis(plt).save("literlymylief.tiff")
I've done a fair amount of research on adding a colorbar to a plot but I'm still really confused about how to add one. The examples I've seen use different ways of doing so, which just confuses me because I don't get what the "right" way is.
I've seen there is a colorbar method and a colorbar() function, so what should one use to simply add a colorbar?
Some examples do this:
fig,ax = plt.subplots()
s = ax.scatter(x,y,cmap = coolwarm)
matplotlib.colorbar.ColorbarBase(ax=ax, cmap=coolwarm, values=sorted(v),
orientation="horizontal")
While some others simply call the function:
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
image = np.random.poisson(10., (100, 80))
i = ax.imshow(image, interpolation='nearest')
fig.colorbar(i)
I'm probably missing something here, but I just don't see how these both create a colorbar (I just copied the code for the colorbar and excluded that of the data).
My question is simply: what is the simplest way to add a colorbar to a plot?
Thanks!
The first example you quote creates an instance of ColorbarBase. This is usually not the recommended way; there might be some exceptions, but in general there is absolutely no reason to use this.
The second example you quote is one or even the way to create a colorbar inside a figure. Using this, you are on the save side. Using the colorbar method of the figure instance makes it clear in which figure to place the colorbar and supplying the respective ScalarMappable (in this case an AxesImage) ensures that the colorbar uses the correct colors from that ScalarMappable.
fig, ax = plt.subplots()
im = ax.imshow(image)
fig.colorbar(im)
or
fig, ax = plt.subplots()
sc = ax.scatter(x,y, c=something)
fig.colorbar(sc)
There is an even easier method, which would be to simply call
plt.colorbar()
Note however that this may lead to confusions as it tries to automatically determine the plot for which the colorbar should be created. Thus, there is some chance that it fails and I would not recommend using it.
I use matplotlib for my plots, I find it great, but sometimes too much complicated. Here an example:
import matplotlib.pyplot as plt
import numpy as np
idx1 = -3
idx2 = 3
x = np.arange(-3, 3, 0.01)
y = np.sin(np.pi*x*7)/(np.pi*x*7)
major_ticks = np.arange(idx1, idx2, 1)
minor_ticks = np.arange(idx1, idx2, 0.1)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_ylim(-0.3, 1.2)
ax.set_xlim(idx1, idx2)
ax.set_xticks(major_ticks)
ax.set_xticks(minor_ticks, minor = True)
ax.grid(True, which = 'both')
ax.tick_params(axis = 'x', labelsize = 18)
ax.tick_params(axis = 'y', labelsize = 18)
ax.plot(x, y)
plt.show()
Is there anything implemented on matplotlib and/or seaborn in which I can provide all these plot settings just as argument of a function only? It may considerably reduce the number of code lines and make the script easier both to write and understand.
Matplotlib provides an object oriented API. This means that all the elements of the figure are acutally objects for which one can get and set properties and which can be easily manipulated. This makes matplotlib really flexible such that it can produce almost any plot you'd imagine.
Since a plot may consist of a hundred or more elements, a function that would allow the same flexibility would need that amount of possible arguments. It is not necessarily easier to remember all possible arguments of a function than all possible attributes of a class.
Having a single function call that does all of this, does not necessarily mean that you have to type in less characters. The commands would just be ordered differently.
Furthermore the object oriented approach allows to keep things seperate. Some properties of the axes, like the grid or the axis labels are completely independend on what you plot to the axes. So you wouldn't want to set the xticks in the call to plot, because they are simply not related and it may be very confusing to set twice the same ticklabels when plotting two lines in the same axes.
On the other hand, matplotlib is really easy. In order to produce a plot you need two lines
import matplotlib.pyplot as plt
plt.plot([1,2,3],[2,1,3])
which sets most of the parameters exactly as they are needed. The more you want to customize this plot, the more settings you have to apply. Which is fine as it allows the user himself to determine how much in depth he wants to control the appearance of the plot.
Most matplotlib codes can be separated into three parts.
Setting the style
Creating the plot
Customizing the plot
Setting the style in the case of the code from the question involves e.g. the ticklabel size and the use of a grid. Those properties can set as it's done in the code but it may indeed be that one always wants to use the same properities here and finds it annoying to type the same parameters in every time one creates a plot. Therefore matplotlib provides general style settings, called rcParams. They can be set at the beginning of a script, e.g.
plt.rcParams['lines.linewidth'] = 2
plt.rcParams['axes.grid '] = True
plt.rcParams['axes.labelsize'] = 18
and will be applied to all plots within the script. It is also possible to define a complete stylesheet using those parameters. For more information see the Customizing matplotlib article.
It is equally possible to use predefined stylesheets for certain applications.
Simply importing import seaborn is also a possible way to change the style.
Creating the plot can not be simplified much more. It's clear that one needs as many plotting commands as items to plot. Creating the figure and axes like
fig, ax = plt.subplots()
saves one line though.
Equally no simplification is possible if customizing ticks or tickmarks are required. One may however consider to use Tickers and Formatters for this purpose.
At the end one may of course consider to write a custom function which performs much of those tasks, but everyone can decide if that is useful for himself.
Browsing around I saw this wabe page.
This line of code can summarise many settings
import matplotlib as mpl
mpl.rc('lines', linewidth=2, color='r')
ax.set is very useful for this:
ax.set(xlim=(idx1, idx2), ylim=(-0.3, 1.2),
xticks=major_ticks, ...)
You can only set simple single-argument properties (e.g. those which don't need further keywords), but it's a nice timesaver.