【问题标题】:Heat map for Irregularly Spaced Data with No Interpolation无插值的不规则间隔数据的热图
【发布时间】:2021-07-02 17:23:18
【问题描述】:

我想绘制一个热图,其中输入数据不在典型的矩形间隔网格中。以下是一些示例数据:

import numpy as np
xmin = 6
xmax= 12
ymin = 0

x = np.linspace(xmin, xmax, 100)
ymax = x**2
final = []

for i in range(len(ymax)):

    yrange = np.linspace(0, ymax[i], 100)

    for j in range(len(yrange)):
        intensity = np.random.rand()
        final.append([x[i], yrange[j], intensity])
    
    
    
data_for_plotting = np.asarray(final) # (10000, 3) shaped array

我想将强度(在颜色栏中)绘制为 (x,y) 的函数,它表示位置,我想在没有插值的情况下这样做。

这是我使用 matplotlib 的 griddata 和线性插值的解决方案。

import matplotlib.pyplot as plt
from matplotlib.mlab import griddata

total_length = 100
x1 = np.linspace(min(data_for_plotting[:,0]), max(data_for_plotting[:,0]), total_length)
y1 = np.linspace(min(data_for_plotting[:,1]), max(data_for_plotting[:,1]), total_length)
z1 = griddata(data_for_plotting[:,0], data_for_plotting[:,1], data_for_plotting[:,2], x1, y1, interp='linear')
p=plt.pcolormesh(x1, y1, z1,  vmin = 0. , vmax=1.0, cmap='viridis')
clb = plt.colorbar(p)
plt.show()

我正在寻找一种无需插值的替代解决方案,因为我希望在我的 x 和 y 位置(像素大小/矩形)中看到最小的测量单位。根据上面给出的示例数据,我预计像素的高度会随着 x 的较大值而增加。

【问题讨论】:

    标签: python-3.x matplotlib scipy seaborn heatmap


    【解决方案1】:

    我不确定matplotlib.mlab.griddata 是关于什么的。也许是一些非常旧的版本?

    您可以使用scipy.interpolate.griddata,它需要格式稍有不同的参数。 method='nearest' 关闭插值(默认method='linear')。

    这是您的测试数据的外观(有关更多解释和示例,请参阅 griddata 的文档):

    import matplotlib.pyplot as plt
    from scipy.interpolate import griddata
    import numpy as np
    
    xmin = 6
    xmax = 12
    ymin = 0
    x = np.linspace(xmin, xmax, 100)
    ymax = x ** 2
    final = []
    for i in range(len(ymax)):
        yrange = np.linspace(0, ymax[i], 100)
        for j in range(len(yrange)):
            intensity = np.random.rand()
            final.append([x[i], yrange[j], intensity])
    data_for_plotting = np.asarray(final)  # (10000, 3) shaped array
    
    total_length = 100
    x1 = np.linspace(min(data_for_plotting[:, 0]), max(data_for_plotting[:, 0]), total_length)
    y1 = np.linspace(min(data_for_plotting[:, 1]), max(data_for_plotting[:, 1]), total_length)
    grid_x, grid_y = np.meshgrid(x1, y1)
    z1 = griddata(data_for_plotting[:, :2], data_for_plotting[:, 2], (grid_x, grid_y), method='nearest')
    img = plt.imshow(z1, extent=[x1[0], x1[-1], y1[0], y1[-1]], origin='lower',
                     vmin=0, vmax=1, cmap='inferno', aspect='auto')
    cbar = plt.colorbar(img)
    plt.show()
    

    另一种方法是为每个延长的像素创建一个矩形。请注意,这可能是一个相当缓慢的操作。如果真的需要,可以为每一列创建一个pcolormesh

    import matplotlib.pyplot as plt
    from matplotlib.cm import ScalarMappable
    import numpy as np
    
    # ... create x and data_for_plotting as before 
    
    fig, ax = plt.subplots()
    cmap = plt.get_cmap('inferno')
    norm = plt.Normalize(0, 1)
    x_step = x[1] - x[0]
    y_step = 0
    for i, (xi, yi, intensity_i) in enumerate(data_for_plotting):
        if i + 1 < len(data_for_plotting) and data_for_plotting[i + 1, 0] == xi:  # when False, the last y_step is reused
            y_step = data_for_plotting[i + 1, 1] - yi
        ax.add_artist(plt.Rectangle((xi, yi), x_step, y_step, color=cmap(norm(intensity_i))))
    cbar = plt.colorbar(ScalarMappable(cmap=cmap, norm=norm))
    ax.set_xlim(x[0], x[-1])
    ax.set_ylim(0, data_for_plotting[:, 1].max())
    plt.tight_layout()
    plt.show()
    

    【讨论】:

    • 通过使用 scipy 或 matplotlib.mlab 对数据进行网格化,我们假设一个插值函数,例如线性或绘制“最近”可用数据点,如您所示。有没有办法在网格化之前绘制实际数据本身?第一个矩形将具有长度 data_for_plotting[:, 0][100] - data_for_plotting[:, 0][0] 和宽度 data_for_plotting[:, 1][1] - data_for_plotting[:, 1][0] 并突出显示整个颜色与 data_for_plotting[:, 2][0] 的值相对应的矩形,并对图中不存在数据的每个点和遮罩区域重复此操作。
    • 基本上,我试图从实际数据中查看像素大小(长 x 宽)。
    猜你喜欢
    • 1970-01-01
    • 2011-10-20
    • 1970-01-01
    • 1970-01-01
    • 2018-12-23
    • 1970-01-01
    • 2016-12-26
    • 2013-10-08
    • 1970-01-01
    相关资源
    最近更新 更多