Change color of seaborn distribution line - python

I want to specify the color of a line of fit within the seaborn package for an array of x and y data. Instead all I can figure out is how to change the color and shading for the kernel density function. How can I change the color for a gaussian fit? I.e. the lines below should be red and blue. It would also be great to shade in the function like the "shade":True argument.
import seaborn as sns
sns.distplot(x,kde_kws={"shade":True}, kde=False, fit=stats.gamma, hist=None, color="red", label="label 1");
sns.distplot(y,kde_kws={"shade":True}, kde=False, fit=stats.gamma, hist=None, color="blue", label="label 2");

For changing the color of the fitted curve, you need to set fit_kws argument. But fit_kws does not support shading. You can still shade the area below the fitted curve by a few extra lines of code as shown below but that I think is an answer to another question that you have posted.
import numpy as np
import seaborn as sns
import scipy.stats as stats
import matplotlib.pyplot as plt
sns.set()
np.random.seed(0)
x = np.random.randn(100)
y = np.random.normal(loc=6.0, scale=1, size=(50,))
ax = sns.distplot(x, fit_kws={"color":"red"}, kde=False,
fit=stats.gamma, hist=None, label="label 1");
ax = sns.distplot(y, fit_kws={"color":"blue"}, kde=False,
fit=stats.gamma, hist=None, label="label 2");
plt.show(block=False)
The result of the code is show below:

Related

Seaborn plot with colorbar, centered around 0

I am trying to change the default behaviour of seaborn by adding a colormap (a continuous color palette) instead of using the hue argument, which creates bins from a continuous variable. I have found the following code to work, however, I would like to add one more option, to center the color bar at 0, that is 0 gets the color white, and the colors diverge from zero to negative/positive.
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
y=np.random.normal(30,30,100)
x=np.random.uniform(0,50,100)
s=sns.scatterplot(
y=y,
x=x,
hue=y,
size=y,
palette='RdBu',
sizes=(50,50)
)
norm=plt.Normalize(y.min(),y.max())
sm=plt.cm.ScalarMappable(cmap="RdBu",norm=norm)
sm.set_array([])
s.get_legend().remove()
s.figure.colorbar(sm)
As can be seen from the image 0 gets a slightly reddish color, because the data is not symmetric about zero. How can I center the colormap around 0? I am completely fine with an inflated colormap from say -80 to 80 (because of the asymmetry) if the center is at 0.
Using the c, norm, and cmap key-word arguments which are passed through from seaborn to matplotlib.axes.Axes.scatter (used to colour the points instead of palette) and create a mcolors.TwoSlopeNorm to create the normalisation centred around zero you can generate the plot like so:
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import matplotlib.colors as mcolors
fig, ax = plt.subplots()
y=np.random.normal(30,30,100)
x=np.random.uniform(0,50,100)
vcenter = 0
vmin, vmax = y.min(), y.max()
normalize = mcolors.TwoSlopeNorm(vcenter=vcenter, vmin=vmin, vmax=vmax)
colormap = cm.RdBu
s=sns.scatterplot(
y=y,
x=x,
c=y,
norm=normalize,
cmap=colormap,
ax=ax,
)
scalarmappaple = cm.ScalarMappable(norm=normalize, cmap=colormap)
scalarmappaple.set_array(y)
fig.colorbar(scalarmappaple)

Seaborn scatter plot increase the thickness of vline marker

I am generating a KDE plot and adding the data points as a scatter plot as well. I am using the vline marker "|" for this scatterplot. How can I increase the thickness of this marker. Increasing s=200 to s=1000 increases the height as well. Is there a way to change the thickness without changing the height?
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
numberList = np.random.rand(20)
ax = sns.kdeplot(numberList)
ax = sns.scatterplot(x=numberList, y=0.1, marker='|', s=200)
plt.show()
I found a solution. Adding a parameter linewidth=3 helped.
ax = sns.scatterplot(x=numberList, y=0.1, marker="|", s=200, linewidth=3)

How to add a standard normal pdf over a seaborn histogram

I would like to add a standard normal pdf curve over a histogram built with seaborn.
import numpy as np
import seaborn as sns
x = np.random.standard_normal(1000)
sns.distplot(x, kde = False)
Any help would be appreciated!
scipy.stats.norm gives easy access to the pdf of a normal distribution with
known parameters; by default it corresponds to the standard normal, mu=0, sigma=1.
This answer works regardless of where the data mean is located (e.g. mu=0 or mu=10)
Tested in python 3.8.11, matplotlib 3.4.2, seaborn 0.11.2
This question and answer are for axes-level plots; for figure-level plots, see How to draw a normal curve on seaborn displot
Imports and Data
import numpy as np
import seaborn as sns
from scipy import stats
import matplotlib.pyplot as plt
# data
np.random.seed(365)
x = np.random.standard_normal(1000)
seaborn.histplot
ax = sns.histplot(x, kde=False, stat='density', label='samples')
# calculate the pdf
x0, x1 = ax.get_xlim() # extract the endpoints for the x-axis
x_pdf = np.linspace(x0, x1, 100)
y_pdf = scipy.stats.norm.pdf(x_pdf)
ax.plot(x_pdf, y_pdf, 'r', lw=2, label='pdf')
ax.legend()
seaborn.distplot - deprecated
For this to correspond correctly to your sampled data, the histogram should
display densities and not counts, so use norm_hist=True in the seaborn.distplot call.
ax = sns.distplot(x, kde = False, norm_hist=True, hist_kws={'ec': 'k'}, label='samples')
# calculate the pdf
x0, x1 = ax.get_xlim() # extract the endpoints for the x-axis
x_pdf = np.linspace(x0, x1, 100)
y_pdf = scipy.stats.norm.pdf(x_pdf)
ax.plot(x_pdf, y_pdf, 'r', lw=2, label='pdf')
ax.legend()

How can I plot identity lines on a seaborn pairplot?

I'm using Seaborn's pairplot:
g = sns.pairplot(df)
Is it possible to draw identity lines on each of the scatter plots?
Define a function which will plot the identity line on the current axes, and apply it to the off-diagonal axes of the grid using PairGrid.map_offdiag() method.
For example:
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
def plot_unity(xdata, ydata, **kwargs):
mn = min(xdata.min(), ydata.min())
mx = max(xdata.max(), ydata.max())
points = np.linspace(mn, mx, 100)
plt.gca().plot(points, points, color='k', marker=None,
linestyle='--', linewidth=1.0)
ds = sns.load_dataset('iris')
grid = sns.pairplot(ds)
grid.map_offdiag(plot_unity)
This makes the following plot on my setup. You can tweak the kwargs of the plot_unity function to style the plot however you want.

how to make rug plot in matplotlib

Im making a density plot with matplotlib and I would also like to get rug plot under it. good example to make density plot is here How to create a density plot in matplotlib?
but I couldn't find any good example for rug plot. in R it can be done easly by rug(data).
You can plot markers at each datapoint.
from scipy import stats
import numpy as np
import matplotlib.pyplot as plt
sample = np.hstack((np.random.randn(30), np.random.randn(20)+5))
density = stats.kde.gaussian_kde(sample)
fig, ax = plt.subplots(figsize=(8,4))
x = np.arange(-6,12,0.1)
ax.plot(x, density(x))
ax.plot(sample, [0.01]*len(sample), '|', color='k')
You can find an example here!
ax = fig.add_subplot(111)
ax.plot(x1, np.zeros(x1.shape), 'b+', ms=20) # rug plot
x_eval = np.linspace(-10, 10, num=200)
ax.plot(x_eval, kde1(x_eval), 'k-', label="Scott's Rule")
ax.plot(x_eval, kde1(x_eval), 'r-', label="Silverman's Rule")
Seems to be the core of it!
You can also use Seaborn.distplot, which wraps histogram, KDE and rugs altogether. Figures made by Seaborn are also prettier by default.
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sample = np.hstack((np.random.randn(30), np.random.randn(20)+5))
fig, ax = plt.subplots(figsize=(8,4))
sns.distplot(sample, rug=True, hist=False, rug_kws={"color": "g"},
kde_kws={"color": "k", "lw": 3})
plt.show()
Here's the answer for people just looking for a rugplot to use on a matplotlib axis: you can use a seaborn function.
import seaborn as sns
sns.rugplot(xdata, height=0.025, axis=ax, color='k')
This looks much nicer than a pure-matplotlib kludge because the rug is aligned to (flush with) the x-axis.

Categories