【问题标题】:Contour/imshow plot for irregular X Y Z data不规则 X Y Z 数据的等高线/imshow 图
【发布时间】:2015-01-16 05:42:40
【问题描述】:

我有 X、Y、Z 格式的数据,其中所有数据都是一维数组,Z 是坐标 (X,Y) 处的测量幅度。我想将此数据显示为等高线或“imshow”图,其中等高线/颜色代表 Z 值(幅度)。

用于测量和 X 和 Y 外观的网格是不规则间隔的。

非常感谢,

len(X)=100

len(Y)=100

len(Z)=100

【问题讨论】:

  • 你试过了吗?你有什么错误吗?
  • 另一篇文章的重点主要是在 2D 中插入不规则数据。我不需要/想要插值。

标签: python plot contour imshow


【解决方案1】:

plt.tricontourf(x,y,z) 是否满足您的要求?

它将为不规则间隔的数据(非直线网格)绘制填充轮廓。

您可能还想查看plt.tripcolor()

import numpy as np
import matplotlib.pyplot as plt
x = np.random.rand(100)
y = np.random.rand(100)
z = np.sin(x)+np.cos(y)
f, ax = plt.subplots(1,2, sharex=True, sharey=True)
ax[0].tripcolor(x,y,z)
ax[1].tricontourf(x,y,z, 20) # choose 20 contour levels, just to show how good its interpolation is
ax[1].plot(x,y, 'ko ')
ax[0].plot(x,y, 'ko ')
plt.savefig('test.png')

【讨论】:

  • 确实是这样,但剧情还是太粗糙了。我正在寻找使它看起来更平滑的方法。谢谢!
  • @Scientist,当我使用tripcolor并让它绘制我生成的(随机)点时,我发现它不能更准确:进行了正确的三角测量,然后根据这些补丁填充三角形节点中的值。
  • 奥利弗,感谢您的意见。我会推,看看我是否可以重新排列一维数组,以便 plt.contour 可以使用它。
  • @Scientist,无需重新排列plt.contour 的值。看看tricontourf(如图)或tricontour(如果你不喜欢填充轮廓)。
  • 想出了一个解决方案:通过增加 tricontour 中的“linewidths”选项,可以实现平滑。干杯...
【解决方案2】:
xx, yy = np.meshgrid(x, y)

plt.contour(xx, yy, z)

不管它们的间距是否不规则,等高线图和 3d 图都需要网格。

【讨论】:

  • Z 在这种情况下必须是二维的。不适用于一维数组。
  • 您确定不想要lines3d 绘图吗?听起来更像是您的数据是为什么而构建的
  • 积极。我需要一个等高线图。当我说它们是一维数组时,我并不是说所有元素都已排序并代表一条线。 x-y 组成了一个很好的 - 不规则间隔的 - 网格,每个点都有一个对应的 Z 值。
  • 如果 Z 是一维数据,它就不适用于等高线图。根据定义,等高线罐要求 Z 值为 2d 矩阵。想想看,轮廓点上的每个值都必须存在于某个 x 和 y 点,所以它必须是 2d。但是可以将 3 条 1-d 线绘制为 lines3d:matplotlib.org/mpl_toolkits/mplot3d/tutorial.html 否则,您将需要 Z 数据成为 X 和 Y 的函数。
  • 我不这么认为!虽然“轮廓”设置为仅接受二维数组......这就是我提出这个问题的原因。 “轮廓点上的每个值都必须存在于某个 x 和 y 点”,绝对正确,这可以通过一维数组来完成。 Z 中的每个元素都对应于具有坐标 (X,Y) 的元素的幅度。这可以在 2-D 中设置,也可以在 1-D 中设置。二维并不是为 X 和 Y 网格分配 Z 值的绝对必要条件。
【解决方案3】:

(源码@完...)

这是我制作的一些视觉糖果。它探讨了网格网格的线性变换仍然是网格网格的事实。 IE。在我所有绘图的左侧,我正在使用 X 和 Y 坐标来实现二维(输入)函数。在右边,我想为同一个函数使用 (AVG(X, Y), Y-X) 坐标。

我尝试在本地坐标中制作网格网格并将它们转换为其他坐标的网格网格。如果变换是线性的,则可以正常工作。

对于底部的两张图,我使用随机抽样直接解决了您的问题。

以下是带有setlims=False 的图片:

setlims=True 也一样:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

def f(x, y):
    return y**2 - x**2
lim = 2
xlims = [-lim , lim]
ylims = [-lim, lim]

setlims = False

pde = 1
numpts = 50
numconts = 20

xs_even = np.linspace(*xlims, num=numpts)
ys_even = np.linspace(*ylims, num=numpts)

xs_rand = np.random.uniform(*xlims, size=numpts**2)
ys_rand = np.random.uniform(*ylims, size=numpts**2)

XS_even, YS_even = np.meshgrid(xs_even, ys_even)

levels = np.linspace(np.min(f(XS_even, YS_even)), np.max(f(XS_even, YS_even)), num=numconts)

cmap = sns.blend_palette([sns.xkcd_rgb['cerulean'], sns.xkcd_rgb['purple']], as_cmap=True)

fig, axes = plt.subplots(3, 2, figsize=(10, 15))

ax = axes[0, 0]
H = XS_even
V = YS_even
Z = f(XS_even, YS_even)
ax.contour(H, V, Z, levels, cmap=cmap)
ax.plot(H.flatten()[::pde], V.flatten()[::pde], linestyle='None', marker='.', color='.75', alpha=0.5, zorder=1, markersize=4)
if setlims:
    ax.set_xlim([-lim/2., lim/2.])
    ax.set_ylim([-lim/2., lim/2.])
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_title('Points on grid, contour')

ax = axes[1, 0]
H = H.flatten()
V = V.flatten()
Z = Z.flatten()
ax.tricontour(H, V, Z, levels, cmap=cmap)
ax.plot(H.flatten()[::pde], V.flatten()[::pde], linestyle='None', marker='.', color='.75', alpha=0.5, zorder=1, markersize=4)
if setlims:
    ax.set_xlim([-lim/2., lim/2.])
    ax.set_ylim([-lim/2., lim/2.])
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_title('Points on grid, tricontour')

ax = axes[0, 1]
H = (XS_even + YS_even) / 2.
V = YS_even - XS_even
Z = f(XS_even, YS_even)
ax.contour(H, V, Z, levels, cmap=cmap)
ax.plot(H.flatten()[::pde], V.flatten()[::pde], linestyle='None', marker='.', color='.75', alpha=0.5, zorder=1, markersize=4)
if setlims:
    ax.set_xlim([-lim/2., lim/2.])
    ax.set_ylim([-lim, lim])
ax.set_xlabel('AVG')
ax.set_ylabel('DIFF')
ax.set_title('Points on transformed grid, contour')

ax = axes[1, 1]
H = H.flatten()
V = V.flatten()
Z = Z.flatten()
ax.tricontour(H, V, Z, levels, cmap=cmap)
ax.plot(H.flatten()[::pde], V.flatten()[::pde], linestyle='None', marker='.', color='.75', alpha=0.5, zorder=1, markersize=4)
if setlims:
    ax.set_xlim([-lim/2., lim/2.])
    ax.set_ylim([-lim, lim])
ax.set_xlabel('AVG')
ax.set_ylabel('DIFF')
ax.set_title('Points on transformed grid, tricontour')

ax=axes[2, 0]
H = xs_rand
V = ys_rand
Z = f(xs_rand, ys_rand)
ax.tricontour(H, V, Z, levels, cmap=cmap)
ax.plot(H[::pde], V[::pde], linestyle='None', marker='.', color='.75', alpha=0.5, zorder=1, markersize=4)
if setlims:
    ax.set_xlim([-lim/2., lim/2.])
    ax.set_ylim([-lim/2., lim/2.])
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_title('Points random, tricontour')

ax=axes[2, 1]
H = (xs_rand + ys_rand) / 2.
V = ys_rand - xs_rand
Z = f(xs_rand, ys_rand)
ax.tricontour(H, V, Z, levels, cmap=cmap)
ax.plot(H[::pde], V[::pde], linestyle='None', marker='.', color='.75', alpha=0.5, zorder=1, markersize=4)
if setlims:
    ax.set_xlim([-lim/2., lim/2.])
    ax.set_ylim([-lim, lim])
ax.set_xlabel('AVG')
ax.set_ylabel('DIFF')
ax.set_title('Points random transformed, tricontour')

fig.tight_layout()

【讨论】:

    【解决方案4】:

    好吧,如果你准备从 Python 转向它的竞争对手 R,我刚刚向 CRAN 提交了一个包(明天或后天应该可以使用),它在非常规网格上进行轮廓绘制——以下可以几行代码就可以实现:

    library(contoureR)
    set.seed(1)
    x = runif(100)
    y = runif(100)
    z = sin(x) + cos(y)
    df = getContourLines(x,y,z,binwidth=0.0005)
    ggplot(data=df,aes(x,y,group=Group)) + 
      geom_polygon(aes(fill=z)) + 
      scale_fill_gradient(low="blue",high="red") + 
      theme_bw()
    

    这会产生以下内容:

    如果你想要一个更规则的网格,并且可以承受一些额外的计算时间:

    x = seq(0,1,by=0.005)
    y = seq(0,1,by=0.005)
    d = expand.grid(x=x,y=y)
    d$z = with(d,sin(x) + cos(y))
    df = getContourLines(d,binwidth=0.0005)
    ggplot(data=df,aes(x,y,group=Group)) + 
      geom_polygon(aes(fill=z)) + 
      scale_fill_gradient(low="blue",high="red") + 
      theme_bw()
    

    上面的模糊边缘,我知道如何解决,应该在下一个版本的软件中修复....

    【讨论】:

      【解决方案5】:

      散点图可能适用于您的情况:

      import numpy as np
      import matplotlib.pyplot as plt
      
      # Generate random data, x,y for coordinates, z for values(amplitude)
      x = np.random.rand(100)
      y = np.random.rand(100)
      z = np.random.rand(100)
      
      # Scatter plot
      plt.scatter(x=x,y=y,c=z)
      

      使用选项c 可视化您的幅度。

      【讨论】:

        【解决方案6】:

        六年后,我可能迟到了一点,但使用 Gouraud 插值对Oliver W.'s answer 进行以下扩展可能会产生“顺利”的结果:

        import numpy as np
        import matplotlib.pyplot as plt
        np.random.seed(1234)  # fix seed for reproducibility
        x = np.random.rand(100)
        y = np.random.rand(100)
        z = np.sin(x)+np.cos(y)
        f, ax = plt.subplots(1,2, sharex=True, sharey=True, clear=True)
        for axes, shading in zip(ax, ['flat', 'gouraud']):
            axes.tripcolor(x,y,z, shading=shading)
            axes.plot(x,y, 'k.')
            axes.set_title(shading)
        plt.savefig('shading.png')
        

        comparison between flat and gouraud shading

        【讨论】:

          猜你喜欢
          • 2021-09-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多