【问题标题】:How to visualize scalar 2D data with Matplotlib?如何使用 Matplotlib 可视化标量 2D 数据?
【发布时间】:2011-07-04 21:38:35
【问题描述】:

所以我有一个网格(矩阵 X 和 Y)以及标量数据(矩阵 Z),我需要将其可视化。最好是一些 2D 图像,在显示 Z 值的点处具有颜色。 我做了一些研究,但没有找到任何符合我想要的东西。

pyplot.imshow(Z) 看起来不错,但它不带我的 X 和 Y 矩阵,所以轴是错误的,它无法处理 X 和 Y 给出的非线性间隔点。

pyplot.pcolor(X,Y,Z) 使用与其中一个角的数据相对应的颜色制作彩色正方形,因此它有点歪曲数据(它应该在其中心或其他地方显示数据)。此外,它忽略了数据矩阵中的两条边。

我很确定在 Matplotlib 的某个地方一定存在一些更好的方法,但是文档很难获得概述。所以我问其他人是否知道更好的方法。如果它允许我刷新矩阵 Z 以制作动画,则奖励。

【问题讨论】:

    标签: python matplotlib


    【解决方案1】:

    这看起来不错,但效率低:

    from pylab import *
    origin = 'lower'
    
    delta = 0.025
    
    x = y = arange(-3.0, 3.01, delta)
    X, Y = meshgrid(x, y)
    Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
    Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
    Z = 10 * (Z1 - Z2)
    
    nr, nc = Z.shape
    
    CS = contourf(
        X, Y, Z,
        levels = linspace(Z.min(), Z.max(), len(x)),
        ls = '-',
        cmap=cm.bone,
        origin=origin)
    
    CS1 = contour(
        CS,
        levels = linspace(Z.min(), Z.max(), len(x)),
        ls = '-',
        cmap=cm.bone,
        origin=origin)
    
    show()
    

    是我,我会重新插入(使用 scipy.interpolate)数据到常规网格并使用 imshow(),设置范围以固定轴。

    编辑(每条评论):

    等高线图的动画可以像这样完成,但是,就像我说的那样,上面的方法效率很低,只是简单地滥用了等高线图功能。做你想做的最有效的方法是使用 SciPy。你安装了吗?

    import matplotlib
    matplotlib.use('TkAgg') # do this before importing pylab
    import time
    import matplotlib.pyplot as plt
    
    fig = plt.figure()
    ax = fig.add_subplot(111)
    
    def animate():
        origin = 'lower'
        delta = 0.025
    
        x = y = arange(-3.0, 3.01, delta)
        X, Y = meshgrid(x, y)
        Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
        Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
        Z = 10 * (Z1 - Z2)
    
        CS1 = ax.contourf(
            X, Y, Z,
            levels = linspace(Z.min(), Z.max(), 10),
            cmap=cm.bone,
            origin=origin)
    
        for i in range(10):
            tempCS1 = contourf(
                X, Y, Z,
                levels = linspace(Z.min(), Z.max(), 10),
                cmap=cm.bone,
                origin=origin)
            del tempCS1
            fig.canvas.draw()
            time.sleep(0.1)
            Z += x/10
    
    win = fig.canvas.manager.window
    fig.canvas.manager.window.after(100, animate)
    plt.show()
    

    【讨论】:

    • 谢谢。是否可以更新此 CS 对象中的数据,以便循环制作某种动画?
    • 是的,我有 Scipy。但我认为 Scipy 使用 Matplotlib 进行所有绘图。它是否也有自己独立的绘图功能?
    • @Eskil:我建议(在我的回答中)使用 scipy 的 interpoate 函数从不规则矩形网格中获取规则矩形网格,然后使用 imshow() 进行更有效的绘图。也就是说,如果您遇到当前解决方案速度慢或效率低的问题。
    • 啊,是的,我应该更仔细地阅读。感谢您的详尽回答。
    • 如果我在循环之前做一个 fig.colorbar(CS1),这个颜色条对新的轮廓是否正确?至少只要我保持“级别”数组不变?
    【解决方案2】:

    如果您的网格网格具有统一间距,您可以继续使用pcolor,但只需移动 X 和 Y,以便将数据集中在特定值而不是角落。

    您还可以使用散点图将一些大小的点明确放置在确切的 X 和 Y 点上,然后将颜色设置为 Z:

    x = numpy.arange(10)
    y = numpy.arange(10)
    X,Y = numpy.meshgrid(x,y)
    Z = numpy.arange(100).reshape((10,10))
    scatter(X,Y,c=Z,marker='s',s=1500) 
    #I picked a marker size that basically overlapped the symbols at the edges
    axis('equal')
    

    或:

    pcolor(X+0.5,Y+0.5,Z)
    axis('equal')
    

    或者按照 Paul 的建议,使用轮廓函数之一

    【讨论】:

      【解决方案3】:

      如果有人在这篇文章中寻找我正在寻找的内容,我将使用上面的示例并将其修改为使用带有帧输入堆栈的 imshow,而不是动态生成和使用轮廓。从名为frames 的形状(nBins、nBins、nBins)图像的 3D 数组开始。

      def animate_frames(frames):
          nBins   = frames.shape[0]
          frame   = frames[0]
          tempCS1 = plt.imshow(frame, cmap=plt.cm.gray)
          for k in range(nBins):
              frame   = frames[k]
              tempCS1 = plt.imshow(frame, cmap=plt.cm.gray)
              del tempCS1
              fig.canvas.draw()
              #time.sleep(1e-2) #unnecessary, but useful
              fig.clf()
      
      fig = plt.figure()
      ax  = fig.add_subplot(111)
      
      win = fig.canvas.manager.window
      fig.canvas.manager.window.after(100, animate_frames, frames)
      

      我还找到了一种更简单的方法来完成整个过程,尽管不太健壮:

      fig = plt.figure()
      
      for k in range(nBins):
          plt.clf()
          plt.imshow(frames[k],cmap=plt.cm.gray)
          fig.canvas.draw()
          time.sleep(1e-6) #unnecessary, but useful
      

      请注意,这两个似乎都只适用于ipython --pylab=tk,也就是backend = TkAgg

      感谢您对一切的帮助。

      【讨论】:

        【解决方案4】:

        以下函数在边界处创建一半大小的框(如附图所示)。

        import matplotlib.pyplot as plt
        import numpy as np
        from scipy.ndimage.filters import convolve
        
        def pcolor_all(X, Y, C, **kwargs):
            X = np.concatenate([X[0:1,:], X], axis=0)
            X = np.concatenate([X[:,0:1], X], axis=1)
        
            Y = np.concatenate([Y[0:1,:], Y], axis=0)
            Y = np.concatenate([Y[:,0:1], Y], axis=1)
        
            X = convolve(X, [[1,1],[1,1]])/4
            Y = convolve(Y, [[1,1],[1,1]])/4
        
            plt.pcolor(X, Y, C, **kwargs)
        
        X, Y = np.meshgrid(
            [-1,-0.5,0,0.5,1],
            [-2,-1,0,1,2])
        
        C = X**2-Y**2
        
        plt.figure(figsize=(4,4))
        
        pcolor_all(X, Y, C, cmap='gray')
        
        plt.savefig('plot.png')
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-09-23
          • 2018-04-23
          • 1970-01-01
          • 2021-11-04
          • 1970-01-01
          • 2016-09-10
          • 1970-01-01
          相关资源
          最近更新 更多