2011-11-08 72 views
2

我正在使用Matplotlib創建等高線圖。我有一個多維數組中的所有數據 。它寬約2000釐米,寬約12釐米。所以它基本上是12列表的長度爲2000的列表。我有等高線圖 工作正常,但我需要平滑數據。我讀了很多 的例子。不幸的是,我沒有數學背景知道什麼是 與他們進行。使用Matplotlib平滑輪廓圖中的數據

那麼,我該如何平滑這些數據呢?我有一個例子,我的圖形看起來像 ,我想讓它看起來更像。

這是我的圖:

graph illustration

我希望它看起來更類似於過什麼:

my goal

我有什麼辦法光滑如在第二等高線圖情節?


我正在使用的數據是從XML文件中提取的。但是,我將顯示陣列的 部分的輸出。由於陣列中的每個元素的長度大約爲2000個,因此I 只會顯示摘錄。

這裏有一個例子:

[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之後,我可以查看這些值,並且他們會更改 。但是,這些變化並不足以影響等值線圖。

回答

10

你可以用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() 

enter image description here

的左側顯示了原始數據,高斯濾波後的右側。

上面的代碼大部分取自Scipy Cookbook,它使用手工製作的高斯內核演示了高斯平滑。由於scipy與內置的相同,我選擇使用gaussian_filter

+0

我曾經看過這個例子。但是,我無法得到這個在我的陣列上工作。我應該注意到我的數組是一個python列表,而不是一個numpy數組。這會造成問題嗎?如果是這樣,將python列表轉換爲numpy數組最簡單的方法是什麼? – dman87

+0

嗯,實際上ndimage.gaussian_filter可以在列表清單上運行得很好。 (例如,'ndimage.gaussian_filter(Z.tolist())'起作用。)問題必須在其他地方。很難說沒有看到數據。什麼不工作意味着什麼?是否引發異常?或者結果看起來不正確? – unutbu

+0

對不起,我應該更具體。我相信這是列表中的數據是字符串的問題。雖然contour()函數並沒有抱怨它。 我得到它沒有錯誤的工作。但是,它根本不會改變輪廓的輸出()。 – dman87

7

平滑數據的一個簡單方法是使用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! 

這兒有用於不同尺寸的窗口的繪製的結果:Results

在此給出的示例代碼使用一個簡單的盒子(或矩形)窗在兩個維度。有幾種不同類型的窗口可用,您可能需要檢查Wikipedia以獲取更多示例。