【问题标题】:Python: Leave Numpy NaN values from matplotlib heatmap and its legend [duplicate]Python:从 matplotlib 热图及其图例中保留 Numpy NaN 值 [重复]
【发布时间】:2016-03-10 00:28:13
【问题描述】:

我有一个需要绘制为热图的 numpy 数组。 numpy 数组还将包含我需要从绘图中排除的 NaN 值。我在其他帖子中被告知 numpy 会自动掩盖图中的 NaN 值,但它对我不起作用。这是一个示例代码

column_labels = list('ABCDEFGH')
row_labels = list('WXYZ')
fig, ax = plt.subplots()
data = np.array([[ 0.96753494,  0.52349944,  0.0254628 ,  0.5104103 ],
         [ 0.07320069,  0.91278731,  0.97094436,  0.70533351],
         [ 0.30162006,  0.49068337,  0.41837729,  0.71139215],
         [ 0.19786101,  0.15882713,  0.59028841,  0.06242765],
         [ 0.51505872,  0.07798389,  0.58790067,  0.44782683],
         [ 0.68975694,  0.53535385,  0.15696023,  0.35641951],
         [ 0.66481995,  0.03576846,  0.9623601 ,  0.96006395],
         [ 0.45865404,  0.50433582,  0.18182575,  0.35126449],])

data[3,:] = np.nan
heatmap = ax.pcolor(data, cmap=plt.cm.seismic)

fig.colorbar(heatmap)
# put the major ticks at the middle of each cell
ax.set_xticks(np.arange(data.shape[1])+0.5, minor=False)
ax.set_yticks(np.arange(data.shape[0])+0.5, minor=False)

# want a more natural, table-like display
ax.invert_yaxis()
ax.xaxis.tick_top()

ax.set_xticklabels(row_labels, minor=False)
ax.set_yticklabels(column_labels, minor=False)
plt.show()

情节看起来像

显然这与没有 Nan 的情节非常不同,看起来像

我想完全避免图例中的 NaN 值,最好用 X 之类的符号对其进行标记。我怎样才能达到同样的效果?

【问题讨论】:

    标签: python numpy matplotlib heatmap nan


    【解决方案1】:

    nans 干扰 pcolor 确定 data 中包含的值的范围,因为

    In [72]: data.min(), data.max()
    Out[72]: (nan, nan)
    

    您可以通过使用np.nanminnp.nanmax 自己声明值的范围来解决此问题,以找到data 中的最小和最大非NaN 值:

    heatmap = ax.pcolor(data, cmap=plt.cm.seismic, 
                        vmin=np.nanmin(data), vmax=np.nanmax(data))
    

    因为

    In [73]: np.nanmin(data), np.nanmax(data)
    Out[73]: (0.025462800000000001, 0.97094435999999995)
    

    import numpy as np
    import matplotlib.pyplot as plt
    
    column_labels = list('ABCDEFGH')
    row_labels = list('WXYZ')
    fig, ax = plt.subplots()
    data = np.array([[ 0.96753494,  0.52349944,  0.0254628 ,  0.5104103 ],
             [ 0.07320069,  0.91278731,  0.97094436,  0.70533351],
             [ 0.30162006,  0.49068337,  0.41837729,  0.71139215],
             [ 0.19786101,  0.15882713,  0.59028841,  0.06242765],
             [ 0.51505872,  0.07798389,  0.58790067,  0.44782683],
             [ 0.68975694,  0.53535385,  0.15696023,  0.35641951],
             [ 0.66481995,  0.03576846,  0.9623601 ,  0.96006395],
             [ 0.45865404,  0.50433582,  0.18182575,  0.35126449],])
    
    data[3,:] = np.nan
    heatmap = ax.pcolor(data, cmap=plt.cm.seismic, 
                        vmin=np.nanmin(data), vmax=np.nanmax(data))
    heatmap.cmap.set_under('black')
    
    bar = fig.colorbar(heatmap, extend='both')
    
    # put the major ticks at the middle of each cell
    ax.set_xticks(np.arange(data.shape[1])+0.5, minor=False)
    ax.set_yticks(np.arange(data.shape[0])+0.5, minor=False)
    
    # want a more natural, table-like display
    ax.invert_yaxis()
    ax.xaxis.tick_top()
    
    ax.set_xticklabels(row_labels, minor=False)
    ax.set_yticklabels(column_labels, minor=False)
    plt.show() 
    


    另一个选项(基于Joe Kington's solution)是绘制 data 为 NaN 时带有阴影标记的矩形补丁。

    上面的例子显示 pcolor 在单元格中的颜色为 NaN 为 尽管 NaN 是非常负数。相比之下,如果你通过pcolor a 蒙版数组pcolor 使蒙版区域保持透明。因此,您可以绘制 坐标区背景补丁 ax.patch 上的影线以显示影线标记 在被遮罩的区域上。

    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.patches as mpatches
    
    column_labels = list('ABCDEFGH')
    row_labels = list('WXYZ')
    fig, ax = plt.subplots()
    data = np.array([[ 0.96753494,  0.52349944,  0.0254628 ,  0.5104103 ],
             [ 0.07320069,  0.91278731,  0.97094436,  0.70533351],
             [ 0.30162006,  0.49068337,  0.41837729,  0.71139215],
             [ 0.19786101,  0.15882713,  0.59028841,  0.06242765],
             [ 0.51505872,  0.07798389,  0.58790067,  0.44782683],
             [ 0.68975694,  0.53535385,  0.15696023,  0.35641951],
             [ 0.66481995,  0.03576846,  0.9623601 ,  0.96006395],
             [ 0.45865404,  0.50433582,  0.18182575,  0.35126449],])
    
    data[3,:] = np.nan
    data = np.ma.masked_invalid(data)
    
    heatmap = ax.pcolor(data, cmap=plt.cm.seismic, 
                        vmin=np.nanmin(data), vmax=np.nanmax(data))
    # https://stackoverflow.com/a/16125413/190597 (Joe Kington)
    ax.patch.set(hatch='x', edgecolor='black')
    fig.colorbar(heatmap)
    
    # put the major ticks at the middle of each cell
    ax.set_xticks(np.arange(data.shape[1])+0.5, minor=False)
    ax.set_yticks(np.arange(data.shape[0])+0.5, minor=False)
    
    # want a more natural, table-like display
    ax.invert_yaxis()
    ax.xaxis.tick_top()
    
    ax.set_xticklabels(row_labels, minor=False)
    ax.set_yticklabels(column_labels, minor=False)
    plt.show() 
    


    如果您希望使用一种以上类型的阴影标记,例如一种用于 NaN,另一种用于负值,那么您可以使用循环来添加阴影矩形:

    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.patches as mpatches
    
    column_labels = list('ABCDEFGH')
    row_labels = list('WXYZ')
    fig, ax = plt.subplots()
    data = np.array([[ 0.96753494,  0.52349944,  0.0254628 ,  0.5104103 ],
             [ 0.07320069,  0.91278731,  0.97094436,  0.70533351],
             [ 0.30162006,  0.49068337,  0.41837729,  0.71139215],
             [ 0.19786101,  0.15882713,  0.59028841,  0.06242765],
             [ 0.51505872,  0.07798389,  0.58790067,  0.44782683],
             [ 0.68975694,  0.53535385,  0.15696023,  0.35641951],
             [ 0.66481995,  0.03576846,  0.9623601 ,  0.96006395],
             [ 0.45865404,  0.50433582,  0.18182575,  0.35126449],])
    data -= 0.5
    data[3,:] = np.nan
    data = np.ma.masked_invalid(data)
    heatmap = ax.pcolor(data, cmap=plt.cm.seismic, 
                        vmin=np.nanmin(data), vmax=np.nanmax(data))
    
    # https://stackoverflow.com/a/16125413/190597 (Joe Kington)
    ax.patch.set(hatch='x', edgecolor='black')
    
    # draw a hatched rectangle wherever the data is negative
    # http://matthiaseisen.com/pp/patterns/p0203/
    mask = data < 0
    for j, i in np.column_stack(np.where(mask)):
          ax.add_patch(
              mpatches.Rectangle(
                  (i, j),     # (x,y)
                  1,          # width
                  1,          # height
                  fill=False, 
                  edgecolor='blue',
                  snap=False,
                  hatch='x' # the more slashes, the denser the hash lines 
              ))
    
    fig.colorbar(heatmap)
    
    # put the major ticks at the middle of each cell
    ax.set_xticks(np.arange(data.shape[1])+0.5, minor=False)
    ax.set_yticks(np.arange(data.shape[0])+0.5, minor=False)
    
    # want a more natural, table-like display
    ax.invert_yaxis()
    ax.xaxis.tick_top()
    
    ax.set_xticklabels(row_labels, minor=False)
    ax.set_yticklabels(column_labels, minor=False)
    plt.show() 
    

    【讨论】:

    • 有没有办法在 nan 值中添加 x 之类的符号
    • 我添加了heatmap.cmap.set_under('black') 以将 NaN 着色为黑色——地震颜色图中没有的颜色。会这样吗?
    • 是否可以添加多个补丁,比如一个用于 NaN,一个用于负值,或者最好通过两次应用掩码数组来实现
    • 我认为叠加技巧只能用于一个舱口。如果您需要两种舱口,您可以使用循环添加第二种。我在上面添加了一个示例来说明我的意思。
    猜你喜欢
    • 1970-01-01
    • 2018-02-04
    • 2020-02-07
    • 2017-01-15
    • 1970-01-01
    • 2021-01-30
    • 2015-12-05
    • 2012-12-09
    • 1970-01-01
    相关资源
    最近更新 更多