美文网首页
scipy.interpolate - 离散数据求根&两组离散数

scipy.interpolate - 离散数据求根&两组离散数

作者: 鱼子酱126 | 来源:发表于2021-03-20 01:36 被阅读0次

    scipy.interpolate - 离散数据求根&两组离散数据求交点

    第一部分:离散数据求根

    import numpy as np
    np.set_printoptions(linewidth=1000)
    
    import matplotlib.pyplot as plt
    # 支持中文
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
    plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
    
    from scipy import interpolate
    
    # 离散点坐标
    X = np.array([5, 7, 12, 13, 14, 16, 18, 22]) 
    # X必须是严格单调递增数据,判断方法:if np.all(np.diff(X)>0)
    Y = np.array([2, 6, 5, 3, 10, -3, 6, 8])
    
    # 显示离散点
    plt.figure(figsize=(12, 6))
    plt.title('两组离散数据与零线')
    plt.xlabel('X')
    plt.ylabel('Y')
    
    plt.plot(
        X, 
        Y, 
        linestyle= 'dashed',
        marker='*',
        label='X,Y离散数据')
    
    plt.plot(
        [X[0], X[-1]], 
        [0, 0], 
        linestyle= '-',
        marker='',
        color = 'black',
        label='零线')
    
    plt.legend()
    plt.show()
    
    png
    # 根据离散点XY构造样条曲线
    # BSpline(builtins.object)
    # tck: A spline, as returned by `splrep` or a BSpline object.
    tck = interpolate.make_interp_spline(x=X, y=Y, k=1) # roots = [ 3.         15.53846154 16.66666667]
    
    # tuple(object)
    # tck: A spline, as returned by `splrep` or a BSpline object.
    #tck = interpolate.splrep(x=X, y=Y, k=1, s=0) # roots = [ 3.         15.53846154 16.66666667]
    
    # k为样条曲线的阶数,k=1为线性,k=2为二次多项式,...
    
    # 转换
    # class PPoly(_PPolyBase); Construct a piecewise polynomial from a spline
    piecewise_polynomial = interpolate.PPoly.from_spline(tck, extrapolate=None)
    # 求根
    roots_X_ = piecewise_polynomial.roots() # class ndarray(builtins.object)
    
    # 在X范围内筛选根
    roots_X = roots_X_[np.where(np.logical_and(roots_X_>=X[0], roots_X_<=X[-1]))]
    print(roots_X)
    
    [15.53846154 16.66666667]
    
    # 显示样条函数
    X_view = np.linspace(X[0], X[-1], 1080) # 类似于分标率080p
    Y_view = piecewise_polynomial(X_view)
    
    # 显示样条函数
    plt.figure(figsize=(12, 6))
    plt.title('离散数据与零线')
    plt.xlabel('X')
    plt.ylabel('Y')
    
    plt.plot(
        X, 
        Y, 
        linestyle= '',
        marker='*',
        label='X,Y离散数据')
    
    plt.plot(
        X_view, 
        Y_view, 
        linestyle= '-',
        label='样条曲线(线性)')
    
    plt.plot(
        [X[0], X[-1]], 
        [0, 0], 
        linestyle= '-',
        marker='',
        color = 'black',
        label='零线')
    
    plt.legend()
    plt.show()
    
    png
    # 封装成函数便于调用
    
    def numpy_scipy_find_roots_by_XY(X, Y, print_=0, plot=0):
        # X必须为严格单调递增数据
        if np.all(np.diff(X) > 0) == True:
            pass
        else:
            raise Exception('X必须为严格单调递增数据!')
    
        # 根据离散点XY构造样条曲线
        # BSpline(builtins.object)
        # tck: A spline, as returned by `splrep` or a BSpline object.
        tck = interpolate.make_interp_spline(x=X, y=Y, k=1) # roots = [ 3.         15.53846154 16.66666667]
    
        # tuple(object)
        # tck: A spline, as returned by `splrep` or a BSpline object.
        #tck = interpolate.splrep(x=X, y=Y, k=1, s=0) # roots = [ 3.         15.53846154 16.66666667]
        # k为样条曲线的阶数,k=1为线性,k=2为二次多项式,...
    
        # 转换
        # class PPoly(_PPolyBase); Construct a piecewise polynomial from a spline
        piecewise_polynomial = interpolate.PPoly.from_spline(tck, extrapolate=None)
        
        # 求根
        roots_X_ = piecewise_polynomial.roots() # class ndarray(builtins.object)
        # 在X范围内筛选根
        roots_X = roots_X_[np.where(np.logical_and(roots_X_>=X[0], roots_X_<=X[-1]))]
        
        
        if print_ == 1:
            print(roots_X)
        
        if plot == 1:
            # 显示样条函数
            X_view = np.linspace(X[0], X[-1], 1080) # 类似于分标率080p
            Y_view = piecewise_polynomial(X_view)
    
            # 显示样条函数
            plt.figure(figsize=(12, 6))
            plt.title('离散数据与零线')
            plt.xlabel('X')
            plt.ylabel('Y')
    
            plt.plot(
                X, 
                Y, 
                linestyle= '',
                marker='*',
                label='X,Y离散数据')
    
            plt.plot(
                X_view, 
                Y_view, 
                linestyle= '-',
                label='样条曲线(线性)')
    
            plt.plot(
                [X[0], X[-1]], 
                [0, 0], 
                linestyle= '-',
                marker='',
                color = 'black',
                label='零线')
    
            plt.legend()
            plt.show()
    
    
        return roots_X
    
    
    # 调用
    roots_X = numpy_scipy_find_roots_by_XY(X=X, Y=Y, print_=1, plot=1)
    
    [15.53846154 16.66666667]
    
    png

    第二部分:两组离散数据求交点

    # 寻找X1、X2的公共定义域
    def numpy_find_commen_definitional_domain_X_by_X1X2(
        X1 = np.array([1, 1.8, 3, 4, 5]), 
        X2 = np.array([2, 3.2, 4.5, 5.1, 6, 8, 11])
        ):
    
        X1.sort()
        X2.sort()
    
        a = np.max([X1[0], X2[0]])
        b = np.min([X1[-1], X2[-1]])
    
        X_full = np.append(X1, X2)
        X_full = np.array(list(set(X_full))) # 去重
        X_full.sort()
        X_commen = X_full[np.where(np.logical_and(X_full>=a, X_full<=b))]
        return X_commen # [2.  3.  3.2 4.  4.5 5. ]
    
    
    # 两组离散数据点(#不允许线段有重合!)
    X1 = [1, 1.8, 3, 6.5, 12]
    Y1 = [5, 5, 9, 6.2, 5]
    
    X2 = [1, 3.2, 4.5, 5.1, 6, 8, 11] # 2
    Y2 = [8, 5, 5, 8, 3, 5, 4]
    
    # 显示离散点(#不允许线段有重合!)
    plt.figure(figsize=(12, 6))
    plt.title('两组离散数据')
    plt.xlabel('X')
    plt.ylabel('Y')
    
    plt.plot(
        X1, 
        Y1, 
        linestyle= 'dashed',
        marker='*',
        label='X1,Y1离散数据')
    
    plt.plot(
        X2, 
        Y2, 
        linestyle= 'dashed',
        marker='*',
        label='X2,Y2离散数据')
    
    plt.legend()
    plt.show()
    
    png
    # 寻找公共定义域(严格单调递增数据)
    X_new = numpy_find_commen_definitional_domain_X_by_X1X2(X1=X1, X2=X2)
    print(X_new)
    
    [ 1.   1.8  3.   3.2  4.5  5.1  6.   6.5  8.  11. ]
    
    Y1_new = np.interp(X_new, X1, Y1)
    Y2_new = np.interp(X_new, X2, Y2)
    Y_new = Y1_new - Y2_new # 作差
    
    # 两离散数据的交点
    inersections_X = numpy_scipy_find_roots_by_XY(X=X_new, Y=Y_new, plot=0)
    inersections_Y = np.interp(inersections_X, X1, Y1)
    print(inersections_X, inersections_Y) # 3个交点
    
    [2.20645161 4.98275862 5.24299065] [6.35483871 7.4137931  7.20560748]
    
    # 封装成函数便于调用
    # 两组离散曲线求交点
    def numpy_scipy_find_inersections_by_X1Y1X2Y2(X1, Y1, X2, Y2, print_=0, plot=0, xlabel='X', ylabel='Y'):
        
        # X1、X2必须为严格单调递增数据
        if np.all(np.diff(X1) > 0) == True:
            pass
        else:
            raise Exception('X1必须为严格单调递增数据!')
    
        if np.all(np.diff(X2) > 0) == True:
            pass
        else:
            raise Exception('X2必须为严格单调递增数据!')
    
        # 寻找公共定义域(严格单调递增数据)
        X_new = numpy_find_commen_definitional_domain_X_by_X1X2(X1=X1, X2=X2)
        #print(X_new)
        Y1_new = np.interp(X_new, X1, Y1)
        Y2_new = np.interp(X_new, X2, Y2)
        Y_new = Y1_new - Y2_new
    
        inersections_X = numpy_scipy_find_roots_by_XY(X=X_new, Y=Y_new, print_=print_, plot= plot)
        inersections_Y = np.interp(inersections_X, X1, Y1)
    
        
    
        if print_ == 1:
            print(inersections_X, inersections_Y)
        
        if plot == 1:
    
            # 显示曲线
            plt.figure(figsize=(12, 6))
            plt.title('两组离散数据的交点')
            plt.xlabel(xlabel)
            plt.ylabel(ylabel)
    
    
            plt.plot(
                X1, 
                Y1, 
                linestyle= '-',
                marker='*',
                label='X1,Y1离散数据')
            
            plt.plot(
                X2, 
                Y2, 
                linestyle= '-',
                marker='*',
                label='X2,Y2离散数据')
    
            plt.legend()
            plt.show()
    
        return inersections_X, inersections_Y
    
    inersections_X, inersections_Y = numpy_scipy_find_inersections_by_X1Y1X2Y2(X1, Y1, X2, Y2, plot=1, print_=1)
    
    [2.20645161 4.98275862 5.24299065]
    
    png
    [2.20645161 4.98275862 5.24299065] [6.35483871 7.4137931  7.20560748]
    
    png

    相关文章

      网友评论

          本文标题:scipy.interpolate - 离散数据求根&两组离散数

          本文链接:https://www.haomeiwen.com/subject/njsicltx.html