Find the intersection of two sets of discrete data

Find the intersection of two sets of discrete data

When doing project research, it is often necessary to solve the intersection of two sets of discrete data. A common approach is to first use a functional model such as a polynomial model or an exponential model to fit the two sets of discrete data, obtain the fitting function, and then use solve to solve the exact solution of the two curves. But this has an obvious limitation. When the two sets of discrete data do not meet any of the above models, the curve fitted by the above model will deviate seriously from the actual discrete data coordinate points, causing errors in the solution results. very large. Therefore, this article solves the intersection of two sets of discrete data (which can be regarded as two piecewise linear functions) and summarizes another solution method, which can directly obtain the exact intersection of two sets of discrete data polylines (linear).

The accuracy of solving the intersection of two sets of discrete data polylines described in this article is determined by the density of the two sets of discrete data given by the user. The denser the two sets of discrete data given by the user, the smoother the piecewise linear function (discrete data polyline) will appear, and the higher the accuracy of the obtained solution will naturally be.

(1) Find the intersection of two sets of discrete data (same sequence X)

Suppose there are two sets of discrete data (same sequence X)

Group 1:

X = [1, 2, 3, 4, 5, 6, 7]
Y1 = [6, 5, 3, 10, 5, 6, 8]

Group 2:

X = [1, 2, 3, 4, 5, 6, 7]
Y2 = [2, 5, 5, 4, 3, 5, 8]

The coordinate points of the two groups of discrete data (the same sequence X) are shown in the figure:

image-20210320012200092

As can be seen from the figure above, there should be a total of 3 intersections between the two sets of discrete data, so we find the intersection of the two sets of discrete data, the code is as follows:

numpy_get_roots_with_two_piecewise_linear_by_same_X.py

import numpy as np
import matplotlib.pyplot as plt
# 支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号



#### 两组离散数据(同X)求交点 ####
def numpy_get_roots_with_two_piecewise_linear_by_same_X(
    Y1 = [6, 5, 3, 10, 5, 6, 8], 
    Y2 = [2, 5, 5, 4, 3, 5, 8], 
    X = None, 
    plot = 0
    ):
    # 注1:Y1与Y2长度相等,每条直线段最多只能有一个交点(不可能有两个)
    # 注1:X的值必须由小到大(X须为单调递增序列)
    if X == None:
        X = [i+1 for i in range(len(Y1))]
    else:
        pass
    
    roots = []
    for i in range(len(Y1)-1):
        Y_i_1 = [Y1[i], Y1[i+1]]
        Y_i_2 = [Y2[i], Y2[i+1]]
        X_i = [X[i], X[i+1]]

        poly_i_1 = np.poly1d(np.polyfit(X_i, Y_i_1, 1))
        poly_i_2 = np.poly1d(np.polyfit(X_i, Y_i_2, 1))
        poly_delta = poly_i_1 - poly_i_2
        
        # 非水平直线函数poly_delta必定有且只有一个解
        root_i = poly_delta.roots[0]
        y = poly_i_1(root_i)
        
        # 减少精度,找回因数据精度损失造成节点处丢失的根
        root_i = round(root_i, 6)
        y = round(y, 6)
        #print((root_i, y), X_i)
        if root_i >=  X_i[0] and root_i <= X_i[1]:
            #print((root_i, y), X_i)
            roots.append((root_i, y))

    if plot == 1:
        # 显示曲线
        plt.figure(figsize=(12, 6))
        plt.title('两组离散数据(相同序列X)求交点')
        plt.xlabel('X')
        plt.ylabel('Y')

        plt.plot(
            X, 
            Y1, 
            marker='*',
            label='X,Y1离散数据')

        plt.plot(
            X, 
            Y2, 
            marker='*',
            label='X,Y2离散数据')

        plt.legend()
        plt.show()

    roots = list(set(roots))
    roots.sort()
    return roots


if __name__ == '__main__':

    roots = numpy_get_roots_with_two_piecewise_linear_by_same_X(Y1=[6, 5, 3, 10, 5, 6, 8], Y2=[2, 5, 5, 4, 3, 5, 8], X=None, plot=1)
    print(roots)

Output the coordinates of the intersection of two sets of discrete data (same sequence X):

[(2.0, 5.0), (3.25, 4.75), (7.0, 8.0)]

(2) Find the intersection of two sets of discrete data (different sequence X)

Suppose there are two sets of discrete data (different sequence X)

Group 1:

X1 = [1, 1.8, 3, 4, 5]
Y1 = [5, 5, 9, 10, 5]

Group 2:

X2 = [2, 3.2, 4.5, 5.1, 6, 8, 11]
Y2 = [8, 5, 5, 8, 3, 5, 4]

The coordinate points of the two groups of discrete data (different sequence X) are shown in the figure:

image-20210320012100475

As can be seen from the above figure, there should be 2 intersection points in total between the two sets of discrete data.

First, convert the two sets of discrete data of different sequences X into two sets of discrete data of the same sequence X as shown below

image-20210320011934092

numpy_get_roots_with_two_piecewise_linear_by_same_X.pyThe function in the call again finds the intersection of two sets of X discrete data in different sequences. The code is as follows:

import numpy as np
import matplotlib.pyplot as plt
# 支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号



from numpy_get_roots_with_two_piecewise_linear_by_same_X import *


# 求交集范围
def X1X2ab(X1ab=(1, 6), X2ab=(5,9)):
    '''
    xa, xb = X1X2ab(X1ab=(X1[0], X1[-1]), X2ab=(X2[0], X2[-1]))
    '''
    X1a = X1ab[0]
    X1b = X1ab[1]
    if X2ab == None:
        X2a = X1a
        X2b = X1b
    else:
        X2a = X2ab[0]
        X2b = X2ab[1]
        if X2a == None:
            X2a = X1a
        if X2b == None:
            X2b = X1b


    # 先确定X2a的位置 , r_left
    if X2a <= X1a:
        r_left = X1a
    elif X1a < X2a and X2a <X1b:
        r_left = X2a
    elif X2a >= X1b:
        return None
    # 再确定X2b的位置, r_right
    if X2b <= X1a:
       return None
    elif X1a < X2b and X2b <X1b:
        r_right = X2b
    elif X2b >= X1b:
        r_right = X1b
    xab = (r_left, r_right)
    return xab





def numpy_get_roots_with_two_piecewise_linear_any(

    X1 = [1, 1.8, 3, 4, 5],
    Y1 = [5, 5, 9, 10, 5],

    X2 = [2, 3.2, 4.5, 5.1, 6, 8, 11],
    Y2 = [8, 5, 5, 8, 3, 5, 4],

    plot = 0

    ):

    # 构造新的X_new
    X_ = X1 + X2
    X_.sort()
    X_new = []
    # 共同定义域
    a, b = X1X2ab(X1ab=(X1[0], X1[-1]), X2ab=(X2[0], X2[-1]))
    for i in X_:
        if i >= a and i <= b:
            X_new.append(i)
    X_new = list(set(X_new)) # 去重
    X_new.sort()
    #print(X_new)

    # 构造新的Y1_new、Y2_new
    Y1_new = np.interp(X_new, X1, Y1)
    Y2_new = np.interp(X_new, X2, Y2)

    roots = numpy_get_roots_with_two_piecewise_linear_by_same_X(Y1=Y1_new, Y2=Y2_new, X=X_new, plot=plot)
    return roots




if __name__ == '__main__':

    X1 = [1, 1.8, 3, 4, 5]
    Y1 = [5, 5, 9, 10, 5]

    X2 = [2, 3.2, 4.5, 5.1, 6, 8, 11]
    Y2 = [8, 5, 5, 8, 3, 5, 4]


    roots = numpy_get_roots_with_two_piecewise_linear_any(X1=X1, Y1=Y1, X2=X2, Y2=Y2, plot=1)
    print(roots)


    plt.figure(figsize=(12, 6))
    plt.title('两组离散数据(不同序列X)求交点')
    plt.xlabel('X')
    plt.ylabel('Y')

    plt.plot(
        X1, 
        Y1, 
        marker='*',
        label='X1,X1离散数据')

    plt.plot(
        X2, 
        Y2, 
        marker='*',
        label='X2,X2离散数据')

    plt.legend()
    plt.show()

Output the coordinates of the intersection of two sets of discrete data (different sequence X):

[(2.4, 7.0), (4.75, 6.25)]

Guess you like

Origin blog.csdn.net/caviar126/article/details/115019626