平滑的循环数据

时间:2016-03-18 00:25:27

标签: python numpy scipy filtering smooth

我有一组数据YY是独立变量X(另一个数组)的函数。

X中的值从0到360不等,包围。

Y中的值从-180到180不等,也是环绕式。

(也就是说,这些值是围绕圆圈的角度。)

有没有人知道Python中的任何函数(numpyscipy等)能够根据YX值进行低通滤波?

如果这一点令人困惑,这里是一个示例数据图:

enter image description here

3 个答案:

答案 0 :(得分:1)

这是使用pandas进行移动平均的解决方案。首先unwrap数据(需要转换为弧度和返回),因此没有不连续性(例如,从180跳到-179)。然后计算移动平均值,如果需要,最后转换回包装数据。另外,请使用np.convolve()查看此numpy cookbook recipe

import numpy as np
import pandas as pd

# generate random data
X = pd.Series([(x  + 5*np.random.random())%360       for x in range(-100, 600, 15)])
Y = pd.Series([(y  + 5*np.random.random())%360 - 180 for y in range(-200, 500, 15)])

# 'unwrap' the angles so there is no wrap around
X1 = pd.Series(np.rad2deg(np.unwrap(np.deg2rad(Y))))
Y1 = pd.Series(np.rad2deg(np.unwrap(np.deg2rad(Y))))

# smooth the data with a moving average
# note: this is pandas 17.1, the api changed for version 18
X2 = pd.rolling_mean(X1, window=3)
Y2 = pd.rolling_mean(Y1, window=3)

# convert back to wrapped data if desired
X3 = X2 % 360
Y3 = (Y2 + 180)%360 - 180

答案 1 :(得分:1)

假设您从

开始
import numpy as np

x = np.linspace(0, 360, 360)
y = 5 * np.sin(x / 90. * 3.14) + np.random.randn(360)

plot(x, y, '+');

enter image description here

要执行循环卷积,您可以执行以下操作:

yy = np.concatenate((y, y))
smoothed = np.convolve(np.array([1] * 5), yy)[5: len(x) + 5]

这在每个点使用具有前5个点(包括)的循环平均值。当然,还有其他方法可以这样做。

>>> plot(x, smoothed)

enter image description here

答案 2 :(得分:0)

您可以使用convolve2D中的scipy.signal。这是一个函数,它对numpy数组a进行平滑处理。如果a具有多个维度,则将平滑应用于最里面(最快)的维度。

import numpy as np
from scipy import signal

def cyclic_moving_av( a, n= 3, win_type= 'boxcar' ):
  window= signal.get_window( win_type, n, fftbins=False ).reshape( (1,n) )
  shp_a= a.shape
  b= signal.convolve2d( a.reshape( ( np.prod( shp_a[:-1], dtype=int ), shp_a[-1] ) ), 
                        window, boundary='wrap', mode='same' )
  return ( b / np.sum( window ) ).reshape( shp_a )

例如,它可以像

一样使用
import matplotlib.pyplot as plt

x = np.linspace(0, 360, 360)
y1 = 5 * np.sin(x / 90. * 3.14) + 0.5 * np.random.randn(360)
y2 = 5 * np.cos(0.8 * x / 90. * 3.14) + 0.5 * np.random.randn(360)

y_av=  cyclic_moving_av( np.stack((y1,y2)), n=10 )  #1

plt.plot(x, y1, '+')
plt.plot(x, y2, '+')
plt.plot(x, y_av[0])
plt.plot(x, y_av[1])
plt.show()

这导致 Cyclic smoothed data

#1行等效于

y_av[0]=  cyclic_moving_av( y1, n=10 )
y_av[1]=  cyclic_moving_av( y2, n=10 )

win_type= 'boxcar'导致对具有相等权重的邻居进行平均。有关其他选项,请参见signal.get_window