【问题标题】:Filled contour using class labels使用类标签填充轮廓
【发布时间】:2018-01-29 02:16:35
【问题描述】:

我有一个二维点网格,其中每个点都有一个对应的标签,在[0.0, 5.0] 范围内。现在我想做以下事情:

绘制网格中的所有点并根据它们的标签为它们着色。

但是,我不想使用scatter plot 来执行此操作。我尝试使用 contourfpcolormesh 绘图:

import matplotlib.pyplot as plt

np.random.seed(1234)

x = np.linspace(-1.0, 1.0, num=5)
xx, yy = np.meshgrid(x, x)
z = np.random.randint(low=0, high=6, size=xx.shape)
levels = np.arange(0, 6)

fig, axes = plt.subplots(nrows=2, ncols=2)
axes[0, 0].contourf(xx, yy, z)
axes[0, 1].contour(xx, yy, z, colors='k')
axes[1, 0].scatter(xx, yy, marker='.', c=z)
axes[1, 1].pcolormesh(xx, yy, z)
plt.show()

我应该如何指定contourf 图的级别,以便获得分隔标签的等高线。 (类似于 pcolormesh 图)

此外,我怎样才能固定每个标签的颜色,即标签 4 应该始终为红色?

编辑:这是一个 contourf 图的示例,它产生了太多的彩色区域:

实际上,网格中只有两个标签。但是,在这两个区域之间的边界处,还绘制了几条额外的等高线。

对于上面的示例,应该有一条等高线分隔两个区域(青色和蓝色)

感谢您的帮助。

【问题讨论】:

  • 我不明白这个问题。使用当前代码,您可以在轮廓图中将标签作为彩色区域。这在多大程度上不是您想要的,实现您需要的问题是什么?
  • 也许您正在寻找plt.clabel?这里是an example

标签: python numpy matplotlib contour


【解决方案1】:

可能您只是忘记提供要显示的关卡。对于 N 个标签,一个需要 7 个级别,例如对于标签[0 1 2 3 4 5],可以选择级别,使标签位于级别区间的中间[-0.5 0.5 1.5 2.5 3.5 4.5 5.5]

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors

np.random.seed(1234)

x = np.linspace(-1.0, 1.0, num=5)
xx, yy = np.meshgrid(x, x)
z = np.random.randint(low=0, high=6, size=xx.shape)

levels = np.arange(0, z.max()+2)-0.5

fig, ax = plt.subplots()
im = ax.contourf(xx, yy, z, levels=levels)

fig.colorbar(im, ax=ax, ticks=np.unique(z))
ax.contour(xx, yy, z, colors='k',levels=levels)
ax.scatter(xx, yy, marker='.', c=z)

plt.show()

请注意,contourf 图的颜色与散点图的颜色略有不同。原因在问题答案中说明:How does pyplot.contourf choose colors from a colormap?

【讨论】:

  • @ThomasKühn 我不确定,也许我们都误解了,只是因为它确实很不清楚。
  • 这回答了我的问题。谢谢!并对造成的误解深表歉意。这是我的第一个问题。下次我会尝试更精确地制定。
【解决方案2】:

如果我理解正确,您需要类似pcolormesh 的情节,但只有轮廓。实现此目的的一种方法是扩展(或扩大)您的数组,使其在xy 方向上多次包含相同的值。这基本上意味着您的z 由许多高原组成,其间有非常陡峭的梯度。您可以使用np.repeat 轻松完成此操作。下面我展示了一个示例,其中原始数据中的每个点都扩展为 20x20 的平台。

可以通过创建自定义颜色图来修复绘图的颜色。在您的情况下,使用 ListedColormap 就足够了。使用contour 时,您还必须指定绘制轮廓的级别以使其正常工作。

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import colors

cmap = colors.ListedColormap([
    'royalblue', 'cyan','yellow', 'orange', 'red', 'green'
])

np.random.seed(1234)

num = 5
x = np.linspace(-1.0, 1.0, num=num)
xx, yy = np.meshgrid(x, x)
z = np.random.randint(low=0, high=6, size=xx.shape)
levels = np.arange(0, 6)

fig, axes = plt.subplots(nrows=2, ncols=2)
axes[0, 0].contourf(xx, yy, z)
axes[0, 1].contour(xx, yy, z, colors='k')
axes[1, 0].scatter(xx, yy, marker='.', c=z)
axes[1, 1].pcolormesh(xx, yy, z, cmap=cmap)  ##I added here the custom colormap for reference

##expanding the arrays
N = 20
x1 = np.linspace(-1.0, 1.0, num=N*num)
xx1, yy1 = np.meshgrid(x1,x1)
z1 = np.repeat(np.repeat(z, N,axis=0),N).reshape(xx1.shape)

fig2, ax2 = plt.subplots()
ax2.contour(xx1, yy1, z1, cmap=cmap, levels = levels)

plt.show()

产生这种情节:

如您所见,线条仍然不是很直,有时可以看到两条相邻的线条。这是因为不同平台之间的梯度不相等。我使用N=200 运行了另一个示例,在这种情况下线条更直:

希望这会有所帮助。

【讨论】:

  • 感谢您的详细回答,但不幸的是这不是我想要的。假设您有一个包含 100 个点的网格,并且网格以 (0,0) 为中心。左边的所有点都有标签 2,右边的所有点都有标签 5。我想要的是一个带有单个轮廓线的轮廓图。即 x = 0 处的垂直线将 2s 与 5s 分开。
  • @MariusMosbach 好的,那么我猜另一个答案就是你想要的。
  • @MariusMosbach 看看我是如何设置颜色图的(我刚刚编辑了答案)——这至少是您在第二个问题中一直在寻找的吗?
猜你喜欢
  • 2022-01-24
  • 1970-01-01
  • 2013-10-13
  • 2021-03-17
  • 2013-01-01
  • 1970-01-01
  • 2015-04-23
  • 1970-01-01
相关资源
最近更新 更多