【问题标题】:change color of bar for data selection in seaborn histogram (or plt)更改 seaborn 直方图(或 plt)中数据选择的条形颜色
【发布时间】:2021-05-25 06:17:23
【问题描述】:

假设我有一个像这样的数据框:

X2 = np.random.normal(10, 3, 200)
X3 = np.random.normal(34, 2, 200)

a = pd.DataFrame({"X3": X3, "X2":X2})

我正在执行以下绘图程序:

f, axes = plt.subplots(2, 2,  gridspec_kw={"height_ratios":(.10, .30)}, figsize = (13, 4))
for i, c in enumerate(a.columns):
    sns.boxplot(a[c], ax=axes[0,i])
    sns.distplot(a[c], ax = axes[1,i])
    axes[1, i].set(yticklabels=[])
    axes[1, i].set(xlabel='')
    axes[1, i].set(ylabel='')

plt.tight_layout()
plt.show()

这会产生:

现在我希望能够对数据框 a 执行数据选择。让我们这样说:

b = a[(a['X2'] <4)]

并在发布的直方图中突出显示来自 b 的选择。 例如,如果 b 的第一行是 X3 的 [32:0] 和 X2 的 [0:5],则所需的输出将是:

可以用上面的for循环和sns来做到这一点吗?非常感谢!

编辑:如果更简单的话,我也对 matplotlib 解决方案感到满意。

编辑2:

如果有帮助,类似的做法如下:

b = a[(a['X3'] >38)]

f, axes = plt.subplots(2, 2,  gridspec_kw={"height_ratios":(.10, .30)}, figsize = (13, 4))

for i, c in enumerate(a.columns):
   sns.boxplot(a[c], ax=axes[0,i])
   sns.distplot(a[c], ax = axes[1,i])
   sns.distplot(b[c], ax = axes[1,i])

   axes[1, i].set(yticklabels=[])
   axes[1, i].set(xlabel='')
   axes[1, i].set(ylabel='')

plt.tight_layout()
plt.show()

产生以下结果:

但是,我希望能够将第一个图中的那些条带上不同的颜色! 我还考虑过将 ylim 设置为仅蓝色图的大小,这样橙色就不会扭曲蓝色分布的形状,但这仍然不可行,因为实际上我有大约 10 个直方图要显示,并且设置 ylim 与 sharey=True 几乎相同,我试图避免这种情况,以便能够显示分布的真实形状。

【问题讨论】:

    标签: pandas matplotlib seaborn distribution


    【解决方案1】:

    我创建以下代码的理解是,您的问题的目的是根据在特定条件下提取的数据为直方图添加不同的颜色。 使用 np.histogram() 获取频率数组和 bin 数组。获取与为某个条件提取的第一行数据的值最接近的值的索引。使用检索到的索引更改直方图的颜色。同样的方法可以用来处理其他的图。

    import seaborn as sns
    import matplotlib.pyplot as plt
    import numpy as np
    import pandas as pd
    
    np.random.seed(2021)
    X2 = np.random.normal(10, 3, 200)
    X3 = np.random.normal(34, 2, 200)
    
    a = pd.DataFrame({"X3": X3, "X2":X2})
    
    f, axes = plt.subplots(2, 2,  gridspec_kw={"height_ratios":(.10, .30)}, figsize = (13, 4))
    for i, c in enumerate(a.columns):
        sns.boxplot(a[c], ax=axes[0,i])
        sns.distplot(a[c], ax = axes[1,i])
        axes[1, i].set(yticklabels=[])
        axes[1, i].set(xlabel='')
        axes[1, i].set(ylabel='')
    
    b = a[(a['X2'] <4)]
    hist3, bins3 = np.histogram(X3)
    idx = np.abs(np.asarray(hist3) - b['X3'].head(1).values[0]).argmin()
    
    for k in range(idx):
        axes[1,0].get_children()[k].set_color("red")
    
    plt.tight_layout()
    plt.show()
    

    【讨论】:

    • 这非常接近,谢谢!但是,我想在 b 数据帧上绘制所有索引,而不仅仅是第一个。我一直在尝试改变您提出idx 的方式,但无法弄清楚@r-beginners
    • 如果有帮助,我想说明的是,一个包含大量变量“X3”的样本可能不包含很多“X2”。换句话说,例如,我想显示 X3 >10 的箱,它们在 X2 中的位置 - 我猜它仍然是 idx 只是子集的不同方式。
    • 如果起始值是从0开始的,我们可以一直处理到循环中找到的索引值。
    • 其实不行。如果我选择 b = a[(a['X3']&gt;38)] ,最终图不会显示超过 38 个 X3 单位的 bin。
    • 我认为发生的情况是新图的 Y 轴太大了,我们再也看不到超过 38。b = a[(a['X3'] &gt; 38)] 中的频率值如下。hist3;array([ 3, 2, 17, 26, 45, 48, 27, 22, 7, 3], dtype=int64)
    【解决方案2】:

    我想我利用上一个答案和this 视频的灵感找到了解决方案:

    import seaborn as sns
    import matplotlib.pyplot as plt
    import numpy as np
    import pandas as pd
    
    np.random.seed(2021)
    X2 = np.random.normal(10, 3, 200)
    X3 = np.random.normal(34, 2, 200)
    
    a = pd.DataFrame({"X3": X3, "X2":X2})
    b = a[(a['X3'] < 30)]
    
    
    hist_idx=[]
    
    for i, c in enumerate(a.columns):
        bin_ = np.histogram(a[c], bins=20)[1]
        hist = np.where(np.logical_and(bin_<=max(b[c]), bin_>min(b[c])))
        hist_idx.append(hist)
        
    
    f, axes = plt.subplots(2, 2,  gridspec_kw={"height_ratios":(.10, .30)}, figsize = (13, 4))
    
    for i, c in enumerate(a.columns):
        sns.boxplot(a[c], ax=axes[0,i])
        axes[1, i].hist(a[c], bins = 20)
        axes[1, i].set(yticklabels=[])
        axes[1, i].set(xlabel='')
        axes[1, i].set(ylabel='')
        
    for it, index in enumerate(hist_idx):
        lenght = len(index[0])
        for r in range(lenght):
            try:
                axes[1, it].patches[index[0][r]-1].set_fc("red")
            except:
                pass 
    
    
    plt.tight_layout()
    plt.show()
    

    b = a[(a['X3'] &lt; 30)] 产生以下结果:

    b = a[(a['X3'] &gt; 36)]

    我想我会把它留在这里 - 虽然小众,但将来可能会对某人有所帮助!

    【讨论】:

      猜你喜欢
      • 2012-08-26
      • 1970-01-01
      • 2022-08-15
      • 1970-01-01
      • 2018-09-01
      • 1970-01-01
      • 2011-08-03
      • 2012-01-19
      • 1970-01-01
      相关资源
      最近更新 更多