代码之家  ›  专栏  ›  技术社区  ›  devpa

Seaborn中的重叠直方图

  •  1
  • devpa  · 技术社区  · 2 年前

    我正在使用Seaborns的histplot函数绘制两个直方图。第一个直方图表示我的整个数据集,而第二个直方图是第一个直方图的子集。然而,第二个直方图似乎并不像预期的那样与第一个直方图重叠。这是我使用的代码:

    import numpy as np
    from scipy.stats import norm
    
    data = np.sin(np.arange(0, 6*np.pi, 0.1)) * 100
    sns.scatterplot(x=[np.mean(data)], y=[0])
    sns.lineplot(data)
    
    population_size = 10000
    sample_size = 100
    total_means = []
    for x in range(population_size):
        total_means.append(np.mean(np.random.choice(data, 100)))
    
    total_means = np.array(total_means)
    sns.histplot(total_means, kde=True)
    
    # Q. Find the range for 68% of data will lie in that interval
    from scipy.stats import norm
    z1 = norm.ppf(.50 - .68/2)
    se = np.array(data).std() / sample_size ** .5
    x1 = z1 * se + np.array(data).mean()
    z2 = norm.ppf(.50 + .68/2)
    x2 = z2 * se + np.array(data).mean()
    print(x1, x2)
    
    plt.xticks(np.arange(total_means.min(), total_means.max(), 10))
    plt.xticks(np.arange(0, 500, 100))
    sns.histplot(total_means, kde=True)
    sns.histplot(total_means[(total_means >= x1) & (total_means <= x2)], kde=True, color='r')
    

    在Stack Overflow上,建议避免发布完整的代码。然而,我有一些数据可以用来快速解决这个问题,而不需要生成新的数据。

    在我的代码中,最后两行绘制了两个直方图。然而,从结果图中可以清楚地看出,这些直方图并没有如预期的那样重叠。

    sns.histplot(total_means, kde=True)
    sns.histplot(total_means[(total_means >= x1) & (total_means <= x2)], kde=True, color='r')
    

    Histogram graph

    2 回复  |  直到 2 年前
        1
  •  3
  •   JohanC    2 年前

    问题是,对于红色图,使用较小的箱(默认值通过 np.histogram_bin_edges() ). 较小的存储箱意味着每个存储箱中的值较少。

    这里有一些代码来显示使用默认bin和对两个直方图使用相同bin之间的区别。子集的第一个和最后一个bin小于较大直方图的bin,因为bin边缘与子集的极限不一致。

    import matplotlib.pyplot as plt
    import seaborn as sns
    import numpy as np
    
    total_means = np.random.randn(2000)
    
    fig, (ax1, ax2) = plt.subplots(ncols=2)
    
    sns.histplot(total_means, kde=True, ax=ax1)
    sns.histplot(total_means[(total_means >= -1) & (total_means <= 1)], kde=True, ax=ax1)
    ax1.set_title('default bins')
    
    bins = np.linspace(total_means.min(), total_means.max(), 30)
    sns.histplot(total_means, bins=bins, kde=True, ax=ax2)
    sns.histplot(total_means[(total_means >= -1) & (total_means <= 1)], bins=bins, kde=True, ax=ax2)
    ax2.set_title('same bins for both')
    
    plt.show()
    

    sns.histplot with same bins

        2
  •  1
  •   ASK    2 年前

    不确定我是否正确理解了你的问题。但是,您提供的代码似乎确实有重叠的图形。只是有一些额外的东西使它难以辨认。

    这也是清理后的样子。如果这就是你想要的,请告诉我。

    import numpy as np
    import matplotlib.pyplot as plt
    import seaborn as sns
    from scipy.stats import norm
    
    data = np.sin(np.arange(0, 6 * np.pi, 0.1)) * 100
    
    population_size = 10000
    sample_size = 100
    total_means = []
    for x in range(population_size):
        total_means.append(np.mean(np.random.choice(data, 100)))
    
    total_means = np.array(total_means)
    
    # Q. Find the range for 68% of data will lie in that interval
    z1 = norm.ppf(.50 - .68 / 2)
    se = np.array(data).std() / sample_size ** .5
    x1 = z1 * se + np.array(data).mean()
    z2 = norm.ppf(.50 + .68 / 2)
    x2 = z2 * se + np.array(data).mean()
    
    plt.xticks(np.arange(total_means.min(), total_means.max(), 10))
    sns.histplot(total_means, kde=True, color='g')
    sns.histplot(total_means[(total_means >= x1) & (total_means <= x2)], kde=True, color='r')
    

    希望这能有所帮助。