【问题标题】:Smoothing Data in Contour Plot with Matplotlib使用 Matplotlib 平滑等高线图中的数据
【发布时间】:2011-12-24 17:23:22
【问题描述】:

我正在使用 Matplotlib 创建等高线图。我有所有的数据 在一个多维数组中。它长12,宽约2000。所以它是 基本上是 12 个列表的列表,长度为 2000。我有等高线图 工作正常,但我需要平滑数据。我读过很多 例子。不幸的是,我没有数学背景来理解什么是 和他们一起去。

那么,我怎样才能平滑这些数据呢?我有一个例子说明我的图表是什么样的 以及我希望它看起来更像什么。

这是我的图表:

我也希望它看起来更相似:

我必须像在第二个图中那样平滑等高线图是什么意思?


我使用的数据是从 XML 文件中提取的。但是,我将显示输出 数组的一部分。由于数组中的每个元素大约有 2000 个项目长,我 只会显示摘录。

这是一个示例:

[27.899999999999999, 27.899999999999999, 27.899999999999999, 27.899999999999999,
 28.0, 27.899999999999999, 27.899999999999999, 28.100000000000001, 28.100000000000001,
 28.100000000000001, 28.100000000000001, 28.100000000000001, 28.100000000000001,
 28.100000000000001, 28.100000000000001, 28.0, 28.100000000000001, 28.100000000000001,
 28.0, 28.100000000000001, 28.100000000000001, 28.100000000000001, 28.100000000000001,
 28.100000000000001, 28.100000000000001, 28.100000000000001, 28.100000000000001,
 28.100000000000001, 28.100000000000001, 28.100000000000001, 28.100000000000001,
 28.100000000000001, 28.100000000000001, 28.100000000000001, 28.100000000000001,
 28.100000000000001, 28.100000000000001, 28.0, 27.899999999999999, 28.0,
 27.899999999999999, 27.800000000000001, 27.899999999999999, 27.800000000000001,
 27.800000000000001, 27.800000000000001, 27.899999999999999, 27.899999999999999, 28.0,
 27.800000000000001, 27.800000000000001, 27.800000000000001, 27.899999999999999,
 27.899999999999999, 27.899999999999999, 27.899999999999999, 28.0, 28.0, 28.0, 28.0,
 28.0, 28.0, 28.0, 28.0, 27.899999999999999, 28.0, 28.0, 28.0, 28.0, 28.0,
 28.100000000000001, 28.0, 28.0, 28.100000000000001, 28.199999999999999,
 28.300000000000001, 28.300000000000001, 28.300000000000001, 28.300000000000001,
 28.300000000000001, 28.399999999999999, 28.300000000000001, 28.300000000000001,
 28.300000000000001, 28.300000000000001, 28.300000000000001, 28.300000000000001,
 28.399999999999999, 28.399999999999999, 28.399999999999999, 28.399999999999999,
 28.399999999999999, 28.300000000000001, 28.399999999999999, 28.5, 28.399999999999999,
 28.399999999999999, 28.399999999999999, 28.399999999999999]

请记住,这只是摘录。数据的维度是 12 行 1959 列。列根据从 XML 导入的数据而变化 文件。我可以在使用 Gaussian_filter 后查看这些值,它们确实如此 改变。但是,这些变化不足以影响等高线图。

【问题讨论】:

    标签: python matplotlib scipy contour smoothing


    【解决方案1】:

    平滑数据的一种简单方法是使用moving average 算法。移动平均的一种简单形式是计算某个位置的相邻测量值的平均值。例如,在一维测量序列 a[1:N] 中,a[n] 处的移动平均值可以计算为 a[n] = (a[n-1] + a[n] + a[例如,n+1]) / 3。如果你完成了所有的测量,你就完成了。在这个简单的示例中,我们的平均窗口大小为 3。您还可以使用不同大小的窗口,具体取决于您想要的平滑程度。

    为了让更广泛的应用程序的计算更容易和更快,您还可以使用基于convolution 的算法。使用卷积的优点是您可以通过简单地更改窗口来选择不同类型的平均值,例如加权平均值。

    让我们做一些编码来说明。以下摘录需要安装 Numpy、Matplotlib 和 Scipy。 Click here 获取完整的运行示例代码

    from __future__ import division
    import numpy
    import pylab
    from scipy.signal import convolve2d
    
    def moving_average_2d(data, window):
        """Moving average on two-dimensional data.
        """
        # Makes sure that the window function is normalized.
        window /= window.sum()
        # Makes sure data array is a numpy array or masked array.
        if type(data).__name__ not in ['ndarray', 'MaskedArray']:
            data = numpy.asarray(data)
    
        # The output array has the same dimensions as the input data 
        # (mode='same') and symmetrical boundary conditions are assumed
        # (boundary='symm').
        return convolve2d(data, window, mode='same', boundary='symm')
    

    以下代码生成一些任意且有噪声的数据,然后使用四个不同大小的框窗口计算移动平均值。

    M, N = 20, 2000  # The shape of the data array
    m, n = 3, 10     # The shape of the window array
    
    y, x = numpy.mgrid[1:M+1, 0:N]
    # The signal and lots of noise
    signal = -10 * numpy.cos(x / 500 + y / 10) / y
    noise = numpy.random.normal(size=(M, N))
    z = signal + noise
    
    # Calculating a couple of smoothed data.
    win = numpy.ones((m, n))
    z1 = moving_average_2d(z, win)
    win = numpy.ones((2*m, 2*n))
    z2 = moving_average_2d(z, win)
    win = numpy.ones((2*m, 4*n))
    z3 = moving_average_2d(z, win)
    win = numpy.ones((2*m, 10*n))
    z4 = moving_average_2d(z, win)
    

    然后,为了查看不同的结果,这里是一些绘图的代码。

    # Initializing the plot
    pylab.close('all')
    pylab.ion()
    fig = pylab.figure()
    bbox = dict(edgecolor='w', facecolor='w', alpha=0.9)
    crange = numpy.arange(-15, 16, 1.) # color scale data range
    
    # The plots
    ax = pylab.subplot(2, 2, 1)
    pylab.contourf(x, y, z, crange)
    pylab.contour(x, y, z1, crange, colors='k')
    ax.text(0.05, 0.95, 'n=10, m=3', ha='left', va='top', transform=ax.transAxes, 
        bbox=bbox)
    
    bx = pylab.subplot(2, 2, 2, sharex=ax, sharey=ax)
    pylab.contourf(x, y, z, crange)
    pylab.contour(x, y, z2, crange, colors='k')
    bx.text(0.05, 0.95, 'n=20, m=6', ha='left', va='top', transform=bx.transAxes, 
        bbox=bbox)
    
    bx = pylab.subplot(2, 2, 3, sharex=ax, sharey=ax)
    pylab.contourf(x, y, z, crange)
    pylab.contour(x, y, z3, crange, colors='k')
    bx.text(0.05, 0.95, 'n=40, m=6', ha='left', va='top', transform=bx.transAxes, 
        bbox=bbox)
    
    bx = pylab.subplot(2, 2, 4, sharex=ax, sharey=ax)
    pylab.contourf(x, y, z, crange)
    pylab.contour(x, y, z4, crange, colors='k')
    bx.text(0.05, 0.95, 'n=100, m=6', ha='left', va='top', transform=bx.transAxes, 
        bbox=bbox)
    
    ax.set_xlim([x.min(), x.max()])
    ax.set_ylim([y.min(), y.max()])
    
    fig.savefig('movingavg_sample.png')
    # That's all folks!
    

    这里是不同大小窗口的绘制结果:

    此处给出的示例代码使用二维的简单框(或矩形)窗口。有几种不同类型的窗口可用,您可能需要查看Wikipedia 以获取更多示例。

    【讨论】:

      【解决方案2】:

      您可以使用gaussian_filter 平滑您的数据:

      import numpy as np
      import matplotlib.pyplot as plt
      import scipy.ndimage as ndimage
      
      X, Y = np.mgrid[-70:70, -70:70]
      Z = np.cos((X**2+Y**2)/200.)+ np.random.normal(size=X.shape)
      
      # Increase the value of sigma to increase the amount of blurring.
      # order=0 means gaussian kernel
      Z2 = ndimage.gaussian_filter(Z, sigma=1.0, order=0)
      fig=plt.figure()
      ax=fig.add_subplot(1,2,1)
      ax.imshow(Z)
      ax=fig.add_subplot(1,2,2)
      ax.imshow(Z2)
      plt.show()
      

      左侧为原始数据,右侧为高斯滤波后的数据。

      上面的大部分代码取自Scipy Cookbook,它演示了使用手工制作的高斯核进行高斯平滑。由于 scipy 内置相同,我选择使用gaussian_filter

      【讨论】:

      • 我以前看过这个例子。但是,我无法让它在我的阵列上工作。我应该注意我的数组是一个 python 列表而不是一个 numpy 数组。这会导致问题吗?如果是这样,将 python 列表转换为 numpy 数组的最简单方法是什么?
      • 嗯,实际上 ndimage.gaussian_filter 可以对列表进行操作就好了。 (例如,ndimage.gaussian_filter(Z.tolist()) 有效。)问题肯定出在其他地方。不看数据很难说。不工作是什么意思?是否引发异常?还是结果看起来不对?
      • 抱歉,我应该更具体一些。我认为列表中的数据是字符串是一个问题。不过,contour() 函数并没有抱怨它。我让它工作没有错误。但是,它根本不会改变 contour() 的输出。
      • 你能用一个简短的例子来编辑你的问题吗?它是字符串列表还是字符串列表,并且是字符串字符串表示形式,例如“1.5”,还是需要struct.unpacked的二进制数据?
      • 我在上面给出了一个简短的摘录。这是在我将字符串转换为浮点数之后。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-22
      • 2013-07-03
      • 2014-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-10
      相关资源
      最近更新 更多