简体   繁体   English

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

[英]Smoothing Data in Contour Plot with Matplotlib

I am working on creating a contour plot using Matplotlib. 我正在使用Matplotlib创建等高线图。 I have all of the data in an array that is multidimensional. 我拥有多维数组中的所有数据。 It is 12 long about 2000 wide. 这是12长约2000宽。 So it is basically a list of 12 lists that are 2000 in length. 所以它基本上是12个长度为2000的列表。 I have the contour plot working fine, but I need to smooth the data. 我的轮廓图工作正常,但我需要平滑数据。 I have read a lot of examples. 我已经阅读了很多例子。 Unfortunately, I don't have the math background to understand what is going on with them. 不幸的是,我没有数学背景来了解他们的情况。

So, how can I smooth this data? 那么,我该如何平滑这些数据呢? I have an example of what my graph looks like and what I want it to look more like. 我有一个关于我的图形看起来像什么以及我希望它看起来更像的例子。

This is my graph: 这是我的图:

图图

What I want it to look more similar too: 我希望它看起来更相似:

我的目标

What means do I have to smooth the contour plot like in second plot? 在第二个图中,我需要用什么方法来平滑轮廓图?


The data I am using is pulled from an XML file. 我正在使用的数据是从XML文件中提取的。 But, I will show the output of part of the array. 但是,我将显示部分数组的输出。 Since each element in the array is around 2000 items long, I will only show an excerpt. 由于数组中的每个元素大约有2000个项目,因此我只会显示一个摘录。

Here is a sample: 这是一个示例:

[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]

Keep in mind this is only an excerpt. 请记住,这只是一个摘录。 The dimension of the data is 12 rows by 1959 columns. 数据的维度是12行乘1959列。 The columns change depending on the data imported from the XML file. 列会根据从XML文件导入的数据而更改。 I can look at the values after I use the Gaussian_filter and they do change. 我可以在使用Gaussian_filter后查看这些值,它们确实会发生变化。 But, the changes are not great enough to affect the contour plot. 但是,这些变化不足以影响等高线图。

You could smooth your data with a 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()

在此输入图像描述

The left-side shows the original data, the right-side after gaussian filtering. 左侧显示原始数据,右侧显示高斯滤波。

Much of the above code was taken from the Scipy Cookbook , which demonstrates gaussian smoothing using a hand-made gauss kernel. 上面的大部分代码都来自Scipy Cookbook ,它使用手工制作的高斯内核演示高斯平滑。 Since scipy comes with the same built in, I chose to use gaussian_filter . 由于scipy带有相同的内置,我选择使用gaussian_filter

One easy way to smooth data is using a moving average algorithm. 平滑数据的一种简单方法是使用移动平均算法。 One simple form of moving average is to calculate the average of adjacent measurements at a certain position. 一种简单的移动平均形式是计算某个位置的相邻测量值的平均值。 In a one-dimensional series of measurements a[1:N], for example, the moving average at a[n] can be calculated as a[n] = (a[n-1] + a[n] + a[n+1]) / 3, for example. 例如,在一维测量系列a [1:N]中,a [n]处的移动平均可以计算为[n] =(a [n-1] + a [n] + a [ n + 1])/ 3,例如。 If you go through all of your measurements, you're done. 如果您完成所有测量,那么您就完成了。 In this simple example, our averaging window has size 3. You can also use windows of different sizes, depending on how much smoothing you want. 在这个简单的示例中,我们的平均窗口的大小为3.您还可以使用不同大小的窗口,具体取决于您想要的平滑程度。

To make the calculations easier and faster for a wider range of applications, you can also use an algorithm based on convolution . 为了使计算更容易,更快,适用于更广泛的应用程序,您还可以使用基于卷积的算法。 The advantage of using convolution is that you can choose different kinds of averages, like weighted averages, by simply changing the window. 使用卷积的优点是您可以通过简单地更改窗口来选择不同类型的平均值,例如加权平均值。

Let's do some coding to illustrate. 我们来做一些编码来说明。 The following excerpt needs Numpy, Matplotlib and Scipy installed. 以下摘录需要安装Numpy,Matplotlib和Scipy。 Click here for the full running sample code 单击此处查看完整运行的示例代码

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')

The following code generates some arbitrary and noisy data and then calculates the moving average using four different sized box windows. 以下代码生成一些任意和噪声数据,然后使用四个不同大小的框窗口计算移动平均值。

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)

And then, to see the different results, here is the code for some plotting. 然后,要查看不同的结果,这里是一些绘图的代码。

# 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!

And here are the plotted results for different sized windows: 以下是不同大小窗口的绘制结果: 结果

The sample code given here uses a simple box (or rectangular) window in two dimensions. 此处给出的示例代码使用二维的简单框(或矩形)窗口。 There are several different kinds of windows available and you might want to check Wikipedia for more examples. 有几种不同类型的窗口,您可能需要查看Wikipedia以获取更多示例。

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

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