在seaborn displot/histplot函数(不是distplot)中绘制适合直方图的高斯图

Use*_*rR6 5 python plot gaussian data-fitting seaborn

我决定试一试seaborn 0.11.0 版!据我所知,使用将替换 distplot 的 displot 函数。我只是想弄清楚如何将高斯拟合绘制到直方图上。这是一些示例代码。

import seaborn as sns
import numpy as np
x = np.random.normal(size=500) * 0.1
Run Code Online (Sandbox Code Playgroud)

使用 distplot 我可以做到:

sns.distplot(x, kde=False, fit=norm)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

但是如何在 displot 或 histplot 中进行呢?

小智 10

fit也真的很怀念这个参数。当他们弃用该功能时,他们似乎并没有替换该distplot功能。在他们堵住这个漏洞之前,我创建了一个简短的函数来将正态分布覆盖添加到我的histplot. 我只需将函数与导入一起粘贴到文件顶部,然后只需添加一行即可在需要时添加覆盖。

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
from scipy import stats

def normal(mean, std, color="black"):
    x = np.linspace(mean-4*std, mean+4*std, 200)
    p = stats.norm.pdf(x, mean, std)
    z = plt.plot(x, p, color, linewidth=2)

data = np.random.normal(size=500) * 0.1    
ax = sns.histplot(x=data, stat="density")
normal(data.mean(), data.std())
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

如果您更愿意使用,stat="probability"而不是stat="density",您可以使用如下方式标准化拟合曲线:

def normal(mean, std, histmax=False, color="black"):
    x = np.linspace(mean-4*std, mean+4*std, 200)
    p = stats.norm.pdf(x, mean, std)
    if histmax:
        p = p*histmax/max(p)
    z = plt.plot(x, p, color, linewidth=2)

data = np.random.normal(size=500) * 0.1    
ax = sns.histplot(x=data, stat="probability")
normal(data.mean(), data.std(), histmax=ax.get_ylim()[1])
Run Code Online (Sandbox Code Playgroud)


cot*_*ail 5

distplot关于参数的源代码fit=与此处其他答案已经建议的非常相似;初始化一些支持数组,使用给定数据的平均值/标准差计算 PDF 值,并将线图叠加在直方图的顶部。我们可以直接将代码的相关部分“转录”为自定义函数,并使用它来绘制高斯拟合(不一定是正态分布;可以是任何连续分布)。

示例实现如下。

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats

def add_fit_to_histplot(a, fit=stats.norm, ax=None):

    if ax is None:
        ax = plt.gca()

    # compute bandwidth
    bw = len(a)**(-1/5) * a.std(ddof=1)
    # initialize PDF support
    x = np.linspace(a.min()-bw*3, a.max()+bw*3, 200)
    # compute PDF parameters
    params = fit.fit(a)
    # compute PDF values
    y = fit.pdf(x, *params)
    # plot the fitted continuous distribution
    ax.plot(x, y, color='#282828')
    return ax

# sample data
x = np.random.default_rng(0).normal(1, 4, size=500) * 0.1

# plot histogram with gaussian fit
sns.histplot(x, stat='density')
add_fit_to_histplot(x, fit=stats.norm);
Run Code Online (Sandbox Code Playgroud)

第一次迭代

如果您不喜欢黑色边缘颜色或一般颜色,我们可以更改条形颜色、边缘颜色和 alpha 参数,以使输出histplot()与已弃用的distplot().

import numpy as np

# sample data
x = np.random.default_rng(0).normal(1, 4, size=500) * 0.1

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10,4))

# left subplot
sns.distplot(x, kde=False, fit=stats.norm, ax=ax1)
ax1.set_title('Using distplot')

# right subplot
sns.histplot(x, stat='density', color='#1f77b4', alpha=0.4, edgecolor='none', ax=ax2)
add_fit_to_histplot(x, fit=stats.norm, ax=ax2)
ax2.set_title('Using histplot+fit');
Run Code Online (Sandbox Code Playgroud)

结果


该答案与现有答案(1 , 2)不同,因为它在有数据的直方图上拟合高斯(或任何其他连续分布,例如伽玛)(这也是在 中绘制拟合的方式distplot())。目的是distplot()尽可能地复制 的 fit 功能。

例如,假设您有遵循泊松分布的数据,绘制其直方图并绘制其高斯拟合。对于add_fit_to_histplot(),因为支持与数据端点相关(并使用斯科特的带宽规则),所以仅在直方图上有相应数据的情况下绘制生成的高斯拟合图,这也是使用(下面的distplot()左侧子图)绘制的方式。另一方面,即使没有相应的数据,ohtotasche的函数也会绘制,即正常 pdf 的左尾被完全绘制(下面的右侧子图)。normal()

data = np.random.default_rng(0).poisson(0.5, size=500)

fig, (a1, a2) = plt.subplots(1, 2, facecolor='white', figsize=(10,4))

# left subplot
sns.histplot(data, stat='density', color='#1f77b4', alpha=0.4, edgecolor='none', ax=a1)
add_fit_to_histplot(data, fit=stats.norm, ax=a1)
a1.set_title("With add_fit_to_histplot")

# right subplot
sns.histplot(x=data, stat="density", ax=a2)
normal(data.mean(), data.std())
a2.set_title("With ohtotasche's normal function")
Run Code Online (Sandbox Code Playgroud)

不同之处


Reg*_*hew 4

抱歉我参加聚会迟到了。只需检查这是否满足您的要求。

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm

data = np.random.normal(size=500) * 0.1
mu, std = norm.fit(data)

# Plot the histogram.
plt.hist(data, bins=25, density=True, alpha=0.6, color='g')

# Plot the PDF.
xmin, xmax = plt.xlim()
x = np.linspace(xmin, xmax, 100)
p = norm.pdf(x, mu, std)
plt.plot(x, p, 'k', linewidth=2)
plt.show()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述