【问题标题】:How to plot a histogram with colored bars in which the coloring should be in accordance to the value in x-axis?如何绘制带有彩色条的直方图,其中颜色应与 x 轴的值一致?
【发布时间】:2020-06-03 15:30:02
【问题描述】:

我编写了一个代码,它给了我一个直方图和一个条形图。我的代码看起来是这样的: `

from math import pi, sin
import numpy as np
import matplotlib.pyplot as plt

plt.style.use('seaborn-whitegrid')

with open('output.txt', 'r') as f:
    lines = f.readlines()
    x = [float(line.split()[12]) for line in lines]

b=[]
a=np.histogram(x,bins=[90,92.5,95,97.5,100,102.5,105,107.5,110,112.5,115,117.5,120,122.5,125,127.5,130,132.5,135,137.5,140,142.5,145,147.5,150,152.5,155,157.5,160,162.5,165,167.5,170,172.5,175,177.5,180])

for i in range(len(a[0])):
    a[0][i]=a[0][i]/sin((91.25 + 2.5*i)*pi/180)
    b.append((91.25 + 2.5*i))

plt.bar(b,a[0],2.5,edgecolor='black')
plt.xlabel('angle($\Theta$)($\circ$)')
plt.ylabel('corrected Frequency')
plt.title('corrected angle distribution')
plt.savefig('Cone_corrected_angle_distribution.jpg', dpi=600)
plt.show()

plt.hist(x,bins=[90,92.5,95,97.5,100,102.5,105,107.5,110,112.5,115,117.5,120,122.5,125,127.5,130,132.5,135,137.5,140,142.5,145,147.5,150,152.5,155,157.5,160,162.5,165,167.5,170,172.5,175,177.5,180],edgecolor='black')
plt.xlabel('angle($\Theta$)($\circ$)')
plt.ylabel('Frequency')
plt.title('Angle distribution')
plt.savefig('angle_distribution.jpg', dpi=600)
plt.show()

` 现在,我想对图表做两处修改:

  1. 我想给直方图的条形着色,使每个条形都有唯一的颜色。条的颜色应根据 x 轴的值。并且x轴下方也应该有一个颜色条供参考。

  2. 我想绘制核分布函数和直方图。我尝试过的方法给了我一个归一化曲线。但我想沿着直方图绘制它。

这将是一个很大的帮助!

【问题讨论】:

    标签: python matplotlib


    【解决方案1】:

    条形图的条形可以通过color= 参数着色,该参数可以是一种特定颜色或一组颜色。直方图不允许使用颜色数组,但返回的矩形可以很容易地在循环中着色。

    kde 是内核密度的估计,最好从原始 x 值计算。它被归一化为表面积为 1,因此只需将其乘以直方图的面积(即所有高度的总和乘以条形宽度)即可获得相似的比例。

    下面的代码首先创建了一些随机数据。原始代码中的不同数组尽可能多地通过 numpy 计算(通过仅在一个位置更改值来更快且通常更具可读性并且更容易创建变体)。

    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.stats import gaussian_kde
    
    x = np.random.normal(135, 15, 1000)
    bin_width = 2.5
    bins_bounds = np.arange(90, 180.01, bin_width)
    bin_values, _ = np.histogram(x, bins=bins_bounds)
    bin_centers = (bins_bounds[:-1] + bins_bounds[1:]) / 2
    bin_values = bin_values / np.sin(bin_centers * np.pi / 180)
    
    plt.style.use('seaborn-whitegrid')
    fig, ax = plt.subplots(ncols=2, figsize=(10, 4))
    cmap = plt.cm.get_cmap('inferno')
    norm = plt.Normalize(vmin=90, vmax=180)
    colors = cmap(norm(bin_centers))
    ax[0].bar(bin_centers, bin_values, bin_width, color=colors, edgecolor='black')
    ax[0].set_xlabel('angle($\Theta$)($\circ$)')
    ax[0].set_ylabel('corrected Frequency')
    ax[0].set_title('corrected angle distribution')
    
    sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
    sm.set_array([])
    fig.colorbar(sm, ax=ax[0], orientation='horizontal')
    
    _, _, bars = ax[1].hist(x, bins=bins_bounds, edgecolor='black')
    for bar, color in zip(bars, colors):
        bar.set_facecolor(color)
    xs = np.linspace(90, 180, 200)
    kde = gaussian_kde(x)
    ax[1]. plot(xs, kde(xs) * len(x) * bin_width, color='dodgerblue', lw=2)
    ax[1].set_xlabel('angle($\Theta$)($\circ$)')
    ax[1].set_ylabel('Frequency')
    ax[1].set_title('Angle distribution')
    fig.colorbar(sm, ax=ax[1], orientation='horizontal')
    plt.tight_layout()
    plt.show()
    

    【讨论】:

    • 感谢 JohanC 的帮助。但我不知道为什么我会遇到这个错误:“AttributeError: 'list' object has no attribute 'size'”
    • 如果x 不是一个numpy 数组,你可以使用len(x) 代替。
    • 谢谢。有效!!。但是有没有办法给第二张图添加边缘颜色?
    • 我刚刚将 set_color(color) 替换为 set_facecolor(color) 以更改条形的颜色,而不会触及边缘颜色。
    • 感谢 JohanC 的帮助。看来你是使用 matplotlib 的专家。我已经彻底搜索了可以帮助我做这些事情的资源,但找不到任何东西。你能给我推荐一些可以帮助我学习这些东西的资源吗?
    猜你喜欢
    • 2019-01-09
    • 2023-02-13
    • 2017-04-26
    • 1970-01-01
    • 2020-09-07
    • 2021-12-06
    • 1970-01-01
    • 2017-10-31
    • 1970-01-01
    相关资源
    最近更新 更多