Using different axis scales in seaborn replot - matplotlib

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)

Related

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.

Matplotlib: Discrete colorbar fails for custom labels

I faced a serious problem when I was trying to add colorbar to scatter plot which indicates in which classes individual sample belongs to. The code works perfectly when classes are [0,1,2] but when the classes are for example [4,5,6] chooses colorbar automatically color values in the end of colormap and colorbar looks blue solid color. I'm missing something obvious but I just can't figure out what it is.
Here is the example code about the problem:
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(1 , figsize=(6, 6))
plt.scatter(datapoints[:,0], datapoints[:,1], s=20, c=labels, cmap='jet', alpha=1.0)
plt.setp(ax, xticks=[], yticks=[])
cbar = plt.colorbar(boundaries=np.arange(len(classes)+1)-0.5)
cbar.set_ticks(np.arange(len(classes)))
cbar.set_ticklabels(classes)
plt.show()
Variables can be for example
datapoints = np.array([[1,1],[2,2],[3,3],[4,4],[5,5],[6,6],[7,7]])
labels = np.array([4,5,6,4,5,6,4])
classes = np.array([4,5,6])
Correct result is got when
labels = np.array([0,1,2,0,1,2,0])
In my case I want it to work also for classes [4,5,6]
The buoundaries need to be in data units. Meaning, if your classes are 4,5,6, you probably want to use boundaries of 3.5, 4.5, 5.5, 6.5.
import matplotlib.pyplot as plt
import numpy as np
datapoints = np.array([[1,1],[2,2],[3,3],[4,4],[5,5],[6,6],[7,7]])
labels = np.array([4,5,6,4,5,6,4])
classes = np.array([4,5,6])
fig, ax = plt.subplots(1 , figsize=(6, 6))
sc = ax.scatter(datapoints[:,0], datapoints[:,1], s=20, c=labels, cmap='jet', alpha=1.0)
ax.set(xticks=[], yticks=[])
cbar = plt.colorbar(sc, ticks=classes, boundaries=np.arange(4,8)-0.5)
plt.show()
If you wanted to have the boundaries determined automatically from the classes, some assumption must me made. E.g. if all classes are subsequent integers,
boundaries=np.arange(classes.min(), classes.max()+2)-0.5
In general, an alternative would be to use a BoundaryNorm, as shown e.g. in Create a discrete colorbar in matplotlib
or How to specify different color for a specific year value range in a single figure? (Python) or python colormap quantisation (matplotlib)

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)

Setting different axis range for seaborn PairGrid

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()

How to change the line color in seaborn linear regression jointplot

As described in the seaborn API the following code will produce a linear regression plot.
import numpy as np, pandas as pd; np.random.seed(0)
import seaborn as sns; sns.set(style="white", color_codes=True)
tips = sns.load_dataset("tips")
g = sns.jointplot(x="total_bill", y="tip", data=tips, kind='reg')
sns.plt.show()
However, with a lot of data points the regression line is not really visible anymore. How can I change its color? I could not find a builtin seaborn command.
In case the line is in the background (i.e. behind the dots), I would also like to ask how to bring it to the front.
There are a couple approaches, as mwaskom tactfully pointed out. You can pass arguments to the joint plot, but setting color there affects the whole scatterplot:
import numpy as np, pandas as pd; np.random.seed(0)
import seaborn as sns#; sns.set(style="white", color_codes=True)
tips = sns.load_dataset("tips")
g = sns.jointplot(x="total_bill", y="tip", data=tips, kind='reg',
joint_kws={'color':'green'}) # Scatter and regression all green
Or pass a dictionary of line-plotting keywords through that dictionary of scatterplot keywords. I read seaborn/linearmodels.py to figure out where to do this, which was entertaining and informative in itself. Dict in dict:
g = sns.jointplot(x="total_bill", y="tip", data=tips, kind='reg',
joint_kws={'line_kws':{'color':'cyan'}}) # Only regression cyan
Or you can access the line after it's been plotted and change it directly. This depends on the regression line being the first line plotted, so could break with seaborn updates. It's also aesthetically/pedagogically different, as you don't recolor the uncertainty spread. It is a good way to get familiar with what the JointGrid object is and how else you might interact with it. (And maybe there are properties you can't set with the function call arguments, although I can't think of any.)
g = sns.jointplot(x="total_bill", y="tip", data=tips, kind='reg')
regline = g.ax_joint.get_lines()[0]
regline.set_color('red')
regline.set_zorder(5)