【问题标题】:How to set histogram color as a gradient?如何将直方图颜色设置为渐变?
【发布时间】:2020-04-01 13:22:07
【问题描述】:

下面是两个图,我试图复制其中的一个左边。该情节是在 Spyder 3.3.6 中制作的——然而,右边的情节也是如此;即,我无法再重现情节。我两次都使用了相同的代码——一些数据上的简单plt.hist(bins=...)——下面是一个最小的变体。使用 Inline、Automatic、Qt5 和 Tkinter 图形后端进行测试,使用 76.0 dpi - 尽管我不记得所有其他设置,当时可能有所不同。

如何让直方图看起来像左边的 - “循环渐变”?


环境。信息:Win-10 操作系统、GTX 1070、Spyder 3.3.6、Python 3.7.5、IPython 7.10.1、Matplotlib 3.1.1


import numpy as np
import matplotlib.pyplot as plt

np.random.seed(2)
x = 0.06*(np.random.uniform(-1, 1, 4000) + 0.05*np.random.randn(4000))

plt.hist(x, bins=400)
plt.gcf().set_size_inches(6, 1.2)
plt.box(None)

提示:默认的matplotlib蓝色为color=[0.121569, 0.466667, 0.705882]

【问题讨论】:

    标签: python matplotlib spyder


    【解决方案1】:

    一个更完整的答案,其中包含与@An0ther0ne 相关的解释,但感谢 OP 展示了该方法的核心。

    这个想法是获取单个直方图条,patches,并根据渐变配色方案通过.set_facecolor() 设置它们的颜色。我们可以生成这样的方案,例如以某种“主色”为中心的正弦函数,以产生所需的效果;应使用 matplotlib 的默认颜色 [0.121569, 0.466667, 0.705882]

    最后,bins_norm = bins / bins.max()bins 归一化为介于-11 之间,因此跨越了两倍的正弦周期,因此我们将在np.sin() 中使用np.pi 而不是2*np.pi


    示例

    import numpy as np
    import matplotlib.pyplot as plt
    
    np.random.seed(2)
    x = 0.06*(np.random.uniform(-1, 1, 8000) + 0.05*np.random.randn(8000))
    
    pretty_hist(x, 400, n_loops=8,  alpha=0.9)
    pretty_hist(x, 400, n_loops=16, alpha=1)
    


    功能

    def pretty_hist(data, bins, n_loops=8, alpha=1, base_color=[0.121569, 0.466667, 0.705882]): 
        N, bins, patches = plt.hist(data, bins=bins, density=True)
        bm = bins.max()
        bins_norm = bins / bm
        bc = base_color
    
        for bin_norm, patch in zip(bins_norm, patches):
            grad = np.sin(np.pi * n_loops * bin_norm) / 15 + .04 
            color = (bc[0] + grad, bc[1] + grad, bc[2] + grad, alpha)
            patch.set_facecolor(color)
    
        plt.gcf().set_size_inches(6, 1)
        plt.box(None)
        plt.show()
    

    内省:我们可以通过在每次迭代中记录grad然后进行绘图来了解它在做什么;对于n_loops=8bins=400

    grads = []
    bin_norm, patch in zip(bins_norm, patches):
            grad = np.sin(np.pi * n_loops * bin_norm) / 15 + .04
            grads.append(grad)
    plt.plot(grads)
    

    【讨论】:

    • 问题不是您可能更改了哪些设置导致了这种情况吗?
    • @ImportanceOfBeingErnest 不,只是让直方图看起来像左边的一个 - 设置或 Pyplot 包括在内。后者肯定更可取,并且被发现了 - 虽然我找不到使它看起来完全相同的颜色组合,但它足够接近,甚至可能更好。
    • @ImportanceOfBeingErnest 作为记录,关于我的另一个问题,刚刚安装了 Spyder 4 - 并且使用相同的设置和 mpl 命令,所有情节质量都非常出色;它就像 SVG,但是是 PNG。因此,图形后端和相关的底层内容实际上可能是罪魁祸首,独立于 matplotlib。
    【解决方案2】:
    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib import colors
    np.random.seed(2)
    x = 0.06*(np.random.uniform(-1, 1, 4000) + 0.05*np.random.randn(4000))
    N, bins, patches = plt.hist(x, bins=400, density=True)
    bm = bins.max()
    fracs = bins / bm
    for thisfrac, thispatch in zip(fracs, patches):
        Green = np.abs(np.sin(thisfrac/bm)/2)
        color = (0,Green,1,1)
        thispatch.set_facecolor(color)
    plt.gcf().set_size_inches(6, 1.2)
    plt.box(None)
    plt.show()
    

    【讨论】:

    • 很好,你已经掌握了方法的根源——虽然,它不是完全一样的蓝色;我寻求的默认 matplotlib 蓝色是 color=[0.121569, 0.466667, 0.705882] - 如果您编辑答案以产生问题中的颜色,那效果最好
    • 还有一些解释也无妨
    • 我自己写的,因为有很多信息需要解压,它应该涵盖解释部分 - 尽管如此,还是赞成你的答案
    猜你喜欢
    • 2019-08-22
    • 2017-03-10
    • 2016-12-15
    • 1970-01-01
    • 1970-01-01
    • 2021-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多