如何用固定点代表色图中间的颜色渐变填充直方图

时间:2018-07-15 10:24:16

标签: matplotlib histogram

此代码

import numpy as np
import matplotlib.pyplot as plt

def randn(n, sigma, mu):
    return sigma * np.random.randn(n) + mu

x = randn(1000, 40., -100.)

cm = plt.cm.get_cmap("seismic")
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
_, bins, patches = ax.hist(x,color="r",bins=30)
bin_centers = 0.5*(bins[:-1]+bins[1:])
col = bin_centers - min(bin_centers)
col /= max(col)

for c, p in zip(col, patches):
    plt.setp(p, "facecolor", cm(c))
plt.savefig("b.png", dpi=300, bbox_inches="tight")

产生以下直方图

This graph should be mostly reddish This graph should be mostly bluish

我想使用发散色图seismic,并且希望将表示出现负数的所有条变为蓝色,并且将表示正数的所有条变为红色。零附近的横条应始终为白色。因此,第一个图应该大部分是红色的,而最后一个图应该主要是蓝色的。我该如何实现?

2 个答案:

答案 0 :(得分:1)

如果这仅是视觉外观,则可以将颜色归一化为最大绝对值和负绝对值之间的范围,以使零始终位于中间(max |bins|)。

import numpy as np; np.random.seed(42)
import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = 6.4,4

def randn(n, sigma, mu):
    return sigma * np.random.randn(n) + mu

x1 = randn(999, 40., -80)
x2 = randn(750, 40., 80)
x3 = randn(888, 16., -30)


def hist(x, ax=None):
    cm = plt.cm.get_cmap("seismic")
    ax = ax or plt.gca()
    _, bins, patches = ax.hist(x,color="r",bins=30)

    bin_centers = 0.5*(bins[:-1]+bins[1:])
    maxi = np.abs(bin_centers).max()
    norm = plt.Normalize(-maxi,maxi)

    for c, p in zip(bin_centers, patches):
        plt.setp(p, "facecolor", cm(norm(c)))


fig, axes = plt.subplots(nrows=3, sharex=True)

for x, ax in zip([x1,x2,x3], axes):
    hist(x,ax=ax)

plt.show()

enter image description here

答案 1 :(得分:1)

对于不同的用例,我有一个替代答案。我希望将发散颜色图中的不同颜色动态地映射到发散点两侧的相应“宽度”。另外,我想明确设置发散点(以我的情况为1)。

我通过修改@ImportanceofBeingErnest的答案来实现这一点,尽管最后我不需要进行任何归一化,我只在同一图形上使用了两个图,并选择了顺序色图,将其放置在-end,重新形成目标发散色图。

def hist2(x, vmin, vmax, cmmap_name, ax=None,):

    cm = plt.cm.get_cmap(cmmap_name)
    ax = ax or plt.gca()
    _, bins, patches = ax.hist(x,color="r",bins=50)

    bin_centers = 0.5*(bins[:-1]+bins[1:])
    norm = plt.Normalize(vmin, vmax)

    for c, p in zip(bin_centers, patches):
        plt.setp(p, "facecolor", cm(norm(c)))

data = <YOUR DATA>
left_data = [i for i in data if i < <YOUR DIVERGENCE POINT>]
right_data = [i for i in data if i >= <YOUR DIVERGENCE POINT>]

fig, ax = plt.subplots(nrows=1)
hist2(left_data, min(left_data), max(left_data), "YlOrRd_r", ax=ax)
hist2(right_data, min(right_data), max(right_data), "YlGn", ax=ax)
plt.show()

我的一些结果:

enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here