繁体   English   中英

使用Matplotlib在等高线图中平滑数据

[英]Smoothing Data in Contour Plot with Matplotlib

我正在使用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后查看这些值,它们确实会发生变化。 但是,这些变化不足以影响等高线图。

您可以使用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

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

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

我们来做一些编码来说明。 以下摘录需要安装Numpy,Matplotlib和Scipy。 单击此处查看完整运行的示例代码

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以获取更多示例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM