Setting different axis range for seaborn PairGrid - matplotlib

I am plotting using seaborn and I am using seaborn.PairGrid function. This is creating 6 x 6 grid, where diagonal plots are histograms and off diagonal plots are scatter plots. Now I want to have different y ranges for each row of plots and different x ranges for each column of the plots. I searched stack exchange a lot but could not find a way to achieve this. Matplot version is 2.0.0 and seaborn version is 0.7.1.
Thanks

You can use the Axes.set_xlim() and Axes.set_ylim() methods on the axes of the seaborn PairGrid or FacetGrid. The axes are available from the PairGrid as .axes attribute.
import matplotlib.pyplot as plt
import seaborn as sns
iris = sns.load_dataset("iris")
g = sns.PairGrid(iris)
g = g.map_diag(plt.hist, edgecolor="k")
g = g.map_offdiag(plt.scatter, s=10)
g.axes[2,0].set_ylim(-10,10)
g.axes[0,1].set_xlim(-40,10)
plt.show()

Related

Multiple marginal plots with Seaborn jointgrid plot

I'd like to draw a jointgrid plot with multiple marginal plots like below:
The reference code is:
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
penguins = sns.load_dataset("penguins")
print(penguins['species'])
plt.figure(figsize=(12,10))
g = sns.JointGrid(data=penguins, x="bill_length_mm", y="bill_depth_mm", hue="species")
g.plot_joint(sns.scatterplot)
g.plot_marginals(sns.boxplot)
plt.show()
If you want stripplot plots on the marginal axes, you could just add the hue parameter:
g = sns.JointGrid(data=penguins, x="bill_length_mm", y="bill_depth_mm", hue="species")
g.plot_joint(sns.scatterplot)
g.plot_marginals(sns.stripplot, hue="species", dodge=True)
But boxplot does not currently handle hue with only one coordinate variable assigned, so you need to draw each marginal plot separately:
g = sns.JointGrid(data=penguins, x="bill_length_mm", y="bill_depth_mm", hue="species")
g.plot_joint(sns.scatterplot)
sns.boxplot(penguins, x=g.hue, y=g.y, ax=g.ax_marg_y)
sns.boxplot(penguins, y=g.hue, x=g.x, ax=g.ax_marg_x)

how to prevent seaborn to skip year in xtick label in Timeseries Plot

I have included the screenshot of the plot. Is there a way to prevent seaborn from skipping the xtick labels in timeseries data.
Most seaborn functions return a matplotlib object, so you can control the number of major ticks displayed via matplotlib. By default, matplotlib will auto-scale, which is why it hides some year labels, you can try to set the MaxNLocator.
Consider the following example:
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# load data
df = sns.load_dataset('flights')
df.drop_duplicates('year', inplace=True)
df.year = df.year.astype('str')
# plot
fig, ax = plt.subplots(figsize=(5, 2))
sns.lineplot(x='year', y='passengers', data=df, ax=ax)
ax.xaxis.set_major_locator(plt.MaxNLocator(5))
This gives you:
ax.xaxis.set_major_locator(plt.MaxNLocator(10))
will give you
Agree with answer of #steven, just want to say that methods for xticks like plt.xticks or ax.xaxis.set_ticks seem more natural to me. Full details can be found here.

Using different axis scales in seaborn replot

I used this example from the Seaborn documentation to produce the figure below.
import seaborn as sns
tips = sns.load_dataset("tips")
g = sns.relplot(x="total_bill", y="tip", hue="day", col="time", data=tips)
How can I force either the x- or y-axis to use different scales (for example have x range from (0, 100) in the right subplot)?
I tried passing sharex=False to the replot function, but that is not a valid keyword.
You need to use facet_kws= to pass the argument to the FacetGrid object. You can then change the limits by referencing each Axes using g.axes which is a 2D array of Axes objects.
import seaborn as sns
tips = sns.load_dataset("tips")
g = sns.relplot(x="total_bill", y="tip", hue="day", col="time", data=tips, facet_kws=dict(sharex=False))
g.axes[0,0].set_xlim(0,100)
g.axes[0,1].set_xlim(20,30)

how to draw axes passing through the origin in a 3D plot using matplotlib

I want to create a 3d plot like the following, such that axes pass through the origin with ticks on them.
PS: I could do that for 2D plots using matplotlib (the following figure). I searched a lot to do the same for 3D plots but I did not find any info.
If you want to restrict yourself to just matplotlib then we can use quiver3d plot as shown below. But the results may not be very visually appealing. You can see here how to add 3D text annotations.
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111,projection='3d')
ax.set_xlim(0,2)
ax.set_ylim(0,2)
ax.set_zlim(0,2)
ax.view_init(elev=20., azim=32)
# Make a 3D quiver plot
x, y, z = np.zeros((3,3))
u, v, w = np.array([[1,1,0],[1,0,1],[0,1,1]])
ax.quiver(x,y,z,u,v,w,arrow_length_ratio=0.1)
plt.show()

Customize the axis label in seaborn jointplot

I seem to have got stuck at a relatively simple problem but couldn't fix it after searching for last hour and after lot of experimenting.
I have two numpy arrays x and y and I am using seaborn's jointplot to plot them:
sns.jointplot(x, y)
Now I want to label the xaxis and yaxis as "X-axis label" and "Y-axis label" respectively. If I use plt.xlabel, the labels goes to the marginal distribution. How can I make them appear on the joint axes?
sns.jointplot returns a JointGrid object, which gives you access to the matplotlib axes and you can then manipulate from there.
import seaborn as sns
import numpy as np
# example data
X = np.random.randn(1000,)
Y = 0.2 * np.random.randn(1000) + 0.5
h = sns.jointplot(X, Y)
# JointGrid has a convenience function
h.set_axis_labels('x', 'y', fontsize=16)
# or set labels via the axes objects
h.ax_joint.set_xlabel('new x label', fontweight='bold')
# also possible to manipulate the histogram plots this way, e.g.
h.ax_marg_y.grid('on') # with ugly consequences...
# labels appear outside of plot area, so auto-adjust
h.figure.tight_layout()
(The problem with your attempt is that functions such as plt.xlabel("text") operate on the current axis, which is not the central one in sns.jointplot; but the object-oriented interface is more specific as to what it will operate on).
Note that the last command uses the figure attribute of the JointGrid. The initial version of this answer used the simpler - but not object-oriented - approach via the matplotlib.pyplot interface.
To use the pyplot interface:
import matplotlib.pyplot as plt
plt.tight_layout()
Alternatively, you can specify the axes labels in a pandas DataFrame in the call to jointplot.
import pandas as pd
import seaborn as sns
x = ...
y = ...
data = pd.DataFrame({
'X-axis label': x,
'Y-axis label': y,
})
sns.jointplot(x='X-axis label', y='Y-axis label', data=data)