importing seaborn stops set rc_params from working - python

When I run the below code it works perfectly fine if the line importing seaborn is commented out, one can set the fontsize in the function and it sets it throughout the plot (I am using it for a more complicated function with several subplots and axes and want a universal font setting). Why is seaborn stopping my with plt.rc_context({'font.size': fontsize,}): from working and how might I stop it doing as such while still being able to make use of seaborn's functionality? (I don't need it's styling defaults though if the solution involves removing those)
import matplotlib.pyplot as plt
import numpy as np
import seaborn
def plotthing(x, y, fontsize=8):
with plt.rc_context({'font.size': fontsize,}):
fig, ax = plt.subplots()
ax.plot(x, y)
ax.set_xlabel("x")
ax.set_xlabel("y")
return fig, ax
x = np.arange(0, 10)
y = 2*x**2
fig, ax = plotthing(x, y, fontsize=2)
fig.savefig("test.pdf")

If you don't want seaborn to make any style changes, you may import the seaborn API alone:
import seaborn.apionly as sns
This also works fine in the case from the question.

I solved this by adding
# reset RC params to original
sns.reset_orig()
After I imported seaborn to undo it's changes to matplotlib's rc params

Related

Statistical significance on matplotlib / seaborn graph?

I finished analyzing my data and want to show that they are statistically significant using the t-test_ind. However, I haven't found anything functional to show this other than what was referenced in (How does one insert statistical annotations (stars or p-values) into matplotlib / seaborn plots?):
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
from statannot import add_stat_annotation
ax = sns.barplot(x=x, y=y, order=order)
add_stat_annotation(ax, data=df, x=x, y=y,
boxPairList=[(order[0], order[1]), (order[0], order[2])],
test='t-test_ind',
textFormat='star',
loc='outside')
Using this approach however, whenever I try to save the plot using plt.savefig() the added significancies using the add_stat_annotation are discared (matplotlib does not seem to recognize the added annotations). Using the loc='inside' option messes up my plot so it isn't really an option.
I am therefore asking if there is some simpler way to add the sigificancies directly in matplotlib / seaborn or if you can plt.savefig() with enough border / padding to include everything.
It was mainly a xlabel cut off problem. So in future applications I would use the add_stat_annotation from webermarcolivier/statannot. To save your files use one of the following possibilities:
import matplotlib.pyplot as plt
plt.tight_layout() # Option 1
plt.autoscale() # Option 2
plt.savefig('filename.png', bbox_inches = "tight") # Option 3
Hope this will help someone for future use.

How to suppress seaborn output when recalling figure object with regplot

I am trying to plot data to a figure and respective axis in matplotlib and as new work comes up, recall the figure with the additional plot on the axis:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
x=np.arange(0,20)
y=2*x
fig,ax=plt.subplots()
ax.scatter(x,x)
ax.scatter(x,y)
fig
Which works fine with matplotlib, if I however use seaborn's regplot:
fig2,ax2=plt.subplots()
sns.regplot(x,x,ax=ax2,fit_reg=False)
sns.regplot(x,y,ax=ax2,fit_reg=False)
fig2
fig2 generates the figure that I want but the regplot command generates an empty figure. Is there a way to suppress the regplot's empty output or have it display the updated ax2 without recalling fig2?
It seems you are using the jupyter notebook with the inline backend. In some circumstances regplot triggers the creation of a new figure even if the artists are being added to the previous one and this messes up the output. I don't know why this happens but I found a workaround that might help you, using plt.ioff to temporarily disable automatic display of figures.
plt.ioff()
fig, ax = plt.subplots()
sns.regplot(x, x, ax=ax)
fig
sns.regplot(x, 2 * x, ax=ax)
fig
You have to call plt.ioff before creating the figure for this to work. After that you have to explicitly display the figure. Then you can call plt.ion to restore the default behaviour.
regplot does not generate an empty figure. According to the documentation:
Understanding the difference between regplot() and lmplot() can be a
bit tricky. In fact, they are closely related, as lmplot() uses
regplot() internally and takes most of its parameters. However,
regplot() is an axes-level function, so it draws directly onto an axes
(either the currently active axes or the one provided by the ax
parameter), while lmplot() is a figure-level function and creates its
own figure, which is managed through a FacetGrid.
When I do the following:
fig2,ax2 = plt.subplots()
same_fig2 = sns.regplot(x,x,ax=ax2,fit_reg=False)
same_fig2.figure is fig2
>>> True

How modules know each other

I can plot data from a CSV file with the following code:
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv('test0.csv',delimiter='; ', engine='python')
df.plot(x='Column1', y='Column3')
plt.show()
But I don't understand one thing. How plt.show() knows about df? I'll make more sense to me seeing, somewhere, an expression like:
plt = something(df)
I have to mention I'm just learning Python.
Matplotlib has two "interfaces": a Matlab-style interface and an object-oriented interface.
Plotting with the Matlab-style interface looks like this:
import matplotlib.pyplot as plt
plt.plot(x, y)
plt.show()
The call to plt.plot implicitly creates a figure and an axes on which to draw.
The call to plt.show displays all figures.
Pandas is supporting the Matlab-style interface by implicitly creating a figure and axes for you when df.plot(x='Column1', y='Column3') is called.
Pandas can also use the more flexible object-oriented interface, in which case
your code would look like this:
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv('test0.csv',delimiter='; ', engine='python')
fig, ax = plt.subplots()
df.plot(ax=ax, x='Column1', y='Column3')
plt.show()
Here the axes, ax, is explicitly created and passed to df.plot, which then
calls ax.plot under the hood.
One case where the object-oriented interface is useful is when you wish to use
df.plot more than once while still drawing on the same axes:
fig, ax = plt.subplots()
df.plot(ax=ax, x='Column1', y='Column3')
df2.plot(ax=ax, x='Column2', y='Column4')
plt.show()
From the pandas docs on plotting:
The plot method on Series and DataFrame is just a simple wrapper
around :meth:plt.plot() <matplotlib.axes.Axes.plot>
So as is, the df.plot method is an highlevel call to plt.plot (using a wrapper), and thereafter, calling plt.show will simply:
display all figures and block until the figures have been closed
as it would with for all figures plotted with plt.plot.
Therefore, you don't see plt = something(df) as you would expect, because matpotlib.pyplot.plot is being called behind the scene by df.plot.
According to http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.show , the plt.show() itself doesn't know about the data, you need to pass the data as parameters.
What you are seeing should be the plot of pandas library, according to the usage http://pandas.pydata.org/pandas-docs/stable/visualization.html#basic-plotting-plot.
Hope this solves your question.

Changing seaborn style in subplots

I'm trying to change the styles of two plots that are in the same figure:
import numpy as np
from numpy.random import randn
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(15,6))
data = randn(7500);
sns.set_style("whitegrid");
ax1.hist(data, bins=8);
sns.set_style("darkgrid");
ax2.hist(data, bins=8);
This does not work, both plots end up having the "darkgrid" background. I have also trying tinkering with axes_style() with no success.
The way matplotlib Axes work is that the style parameters become a property of the Axes object at the time it is created, not at the time something is drawn onto it. So while it's not possible to make a figure that has different subplot styles using plt.subplots, you can do it with one of the ways where you independently create the Axes:
fig = plt.figure()
with sns.axes_style("whitegrid"):
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)
Note also that I'm using a context manager to style the first Axes, so the second Axes will have the default style. It's possible to use sns.set_style before each add_subplot command like you do in the question, but using the context manager to create the non-default plot feels a little bit more Pythonic.

Why do pyplot methods apply instantly and subplot axes methods do not?

I'm editing my graphs step by step. Doing so, plt functions from matplotlib.pyplot apply instantly to my graphical output of pylab. That's great.
If I address axes of a subplot, it does not happen anymore.
Please find both alternatives in my minimal working example.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
f = plt.figure()
sp1 = f.add_subplot(1,1,1)
f.show()
# This works well
sp1.set_xlim([1,5])
# Now I plot the graph
df = pd.Series([0,5,9,10,15])
df.hist(bins=50, color="red", alpha=0.5, normed=True, ax=sp1)
# ... and try to change the ticks of the x-axis
sp1.set_xticks(np.arange(1, 15, 1))
# Unfortunately, it does not result in an instant change
# because my plot has already been drawn.
# If I wanted to use the code above,
# I would have to execute him before drawing the graph.
# Therefore, I have to use this function:
plt.xticks(np.arange(1, 15, 1))
I understand that there is a difference between matplotlib.pyplot and an axis instance. Did I miss anything or does it just work this way?
Most of pyplot functions (if not all) have a call to plt.draw_if_interactive() before returning. So if you do
plt.ion()
plt.plot([1,2,3])
plt.xlim([-1,4])
you obtain that the plot is updated as you go. If you have interactive off, it won't create or update the plot until you don't call plt.show().
But all pyplot functions are wrappers around corresponding (usually) Axes methods.
If you want to use the OO interface, and still draw stuff as you type, you can do something like this
plt.ion() # if you don't have this, you probably don't get anything until you don't call a blocking `plt.show`
fig, ax = plt.subplots() # create an empty plot
ax.plot([1,2,3]) # create the line
plt.draw() # draw it (you can also use `draw_if_interactive`)
ax.set_xlim([-1,4]) #set the limits
plt.draw() # updata the plot
You don't have to use the pyplot you don't want, just remember to draw
The plt.xticks() method calls a function draw_if_interactive() that comes from pylab_setup(), who is updating the graph. In order to do it using sp1.set_xticks(), just call the corresponding show() method:
sp1.figure.show()

Categories

Resources