2

我有一个重复信号,该信号在一个大致每秒重复一次的过程的每个周期中会发生一些变化,尽管每个周期的持续时间和内容在某些参数内会有所不同。我的信号数据的每一秒都有一千个 x,y 坐标。每个周期内的一小部分但重要的数据已损坏,我想用向上的抛物线替换每个损坏的部分。

对于需要用抛物线替换的每个数据段,我有三个点的 x,y 坐标。顶点/最小值是这些点之一。而另外两个点是向上的U形即抛物线的左右顶部。换句话说,左上角是该函数域中最低 x 值的 x,y 坐标对,而右上角是该函数域中最高 x 值的 x,y 坐标对。左上和右上的 y 坐标相等,是数据段中最高的两个 y 值。

如何编写代码来绘制这条向上抛物线中的剩余数据点? 请记住,每分钟数据需要调用此函数 60 或 70 次,并且每次调用此函数时抛物线的形状/公式都需要更改,以说明这三对之间的不同关系每个结果抛物线中的 x,y 坐标。

def ReplaceCorruptedDataWithParabola(Xarray, Yarray, LeftTopX, LeftTopY
                                     , LeftTopIndex, MinX, MinY, MinIndex
                                     , RightTopX, RightTopY, RightTopIndex):  

    # Step One: Derive the formula for the upward-facing parabola using 
    # the following data from the three points:
        LeftTopX,LeftTopY,LeftTopIndex  
        MinX,MinY,MinIndex  
        RightTopX,RightTopY,RightTopIndex 

    # Step Two: Use the formula derived in step one to plot the parabola in
    # the places where the corrupted data used to reside:
    for n in Xarray[LeftTopX:RightTopX]:
        Yarray[n]=[_**The formula goes here**_]

    return Yarray 

注意:Xarray 和 Yarray 都是单列向量,每个索引处都有数据,将两个数组链接为 x,y 坐标集。它们都是 numpy 数组。Xarray 包含时间信息并且不会改变,但 Yarray 包含信号数据,包括将被替换为需要通过此函数计算的抛物线数据的损坏段。

4

1 回答 1

7

因此,据我了解,您有 3 个点需要拟合抛物线。

通常,只使用numpy.polyfit是最简单的,但如果你真的担心速度,并且你正好拟合三个点,那么使用最小二乘拟合是没有意义的。

相反,我们有一个偶数确定的系统(将抛物线拟合到 3 个 x,y 点),我们可以用简单的线性代数得到一个精确的解决方案。

所以,总而言之,你可能会做这样的事情(其中大部分是绘制数据):

import numpy as np                                                                              
import matplotlib.pyplot as plt                                                                 

def main():
    # Generate some random data
    x = np.linspace(0, 10, 100)
    y = np.cumsum(np.random.random(100) - 0.5)

    # Just selecting these arbitrarly 
    left_idx, right_idx = 20, 50      
    # Using the mininum y-value within the arbitrary range
    min_idx = np.argmin(y[left_idx:right_idx]) + left_idx 

    # Replace the data within the range with a fitted parabola
    new_y = replace_data(x, y, left_idx, right_idx, min_idx)  

    # Plot the data
    fig = plt.figure()
    indicies = [left_idx, min_idx, right_idx]

    ax1 = fig.add_subplot(2, 1, 1)
    ax1.axvspan(x[left_idx], x[right_idx], facecolor='red', alpha=0.5)
    ax1.plot(x, y)                                                    
    ax1.plot(x[indicies], y[indicies], 'ro')                          

    ax2 = fig.add_subplot(2, 1, 2)
    ax2.axvspan(x[left_idx], x[right_idx], facecolor='red', alpha=0.5)
    ax2.plot(x,new_y)                                                 
    ax2.plot(x[indicies], y[indicies], 'ro')

    plt.show()

def fit_parabola(x, y):
    """Fits the equation "y = ax^2 + bx + c" given exactly 3 points as two
    lists or arrays of x & y coordinates"""
    A = np.zeros((3,3), dtype=np.float)
    A[:,0] = x**2
    A[:,1] = x
    A[:,2] = 1
    a, b, c = np.linalg.solve(A, y)
    return a, b, c

def replace_data(x, y, left_idx, right_idx, min_idx):
    """Replace the section of "y" between the indicies "left_idx" and
    "right_idx" with a parabola fitted to the three x,y points represented
    by "left_idx", "min_idx", and "right_idx"."""
    x_fit = x[[left_idx, min_idx, right_idx]]
    y_fit = y[[left_idx, min_idx, right_idx]]
    a, b, c = fit_parabola(x_fit, y_fit)

    new_x = x[left_idx:right_idx]
    new_y = a * new_x**2 + b * new_x + c

    y = y.copy() # Remove this if you want to modify y in-place
    y[left_idx:right_idx] = new_y
    return y

if __name__ == '__main__':
    main()

示例图

希望那有所帮助...

于 2010-10-29T03:16:04.187 回答