如何找到所有负斜率直线并获得最小 y=0 值的直线

How to find all negative slope straight lines and get the one with the minimum y=0 value

我想实现一个绘制直方图的函数,并计算使用 bin 坐标计算的所有负斜率直线的最小 y=0 值。

比如这个情节:

i1s1=[1.081576, 1.063301000000001, 0.7665449999999989, 0.6702140000000014, 0.9948089999999983, 0.8247, 
      1.0281650000000013, 1.0204430000000002, 0.9952000000000005, 0.8824919999999992, 1.0094080000000005, 
      0.23627600000000015, 0.7032509999999981, 0.34252400000000094, 0.5976010000000009, 0.9419879999999985, 
      1.1269390000000001, 1.0165110000000013, 0.803722999999998, 1.2493930000000013, 0.3798589999999997, 
      0.5761640000000021, 1.0876199999999976, 0.8915590000000009, 0.9461050000000029, 1.0046489999999935, 
      0.8577720000000042, 1.131541999999996, 0.9394370000000052, 1.939746999999997, 0.7513170000000002, 
      0.7799210000000016, 0.2271250000000009, 0.5776759999999967, 1.0690549999999988, 1.2057460000000049, 
      2.6899219999999957, 3.521351000000003, 0.8345109999999991, 1.1897260000000003, 0.9561250000000001, 
      2.113745999999999, 0.7494179999999986, 1.1265460000000047, 0.8125209999999967, 2.5974119999999985, 
      0.7458990000000014, 1.0843160000000012, 0.9465989999999991, 0.8917330000000021, 0.933920999999998, 
      2.2939850000000064, 1.3038799999999924, 1.7666460000000086]
n, bins, patches = plt.hist(x=i1s1, bins='auto', color='#0504aa',
                            alpha=0.6, rwidth=0.9,)
plt.grid(axis='y', alpha=0.35)
plt.xlabel('time [s]')
plt.ylabel('Frequency')
plt.show()

每个bin的坐标可以这样计算:

midpoints = bins[:-1] + np.diff(bins)/2
coords = np.column_stack((midpoints,n))
coords = array([[ 0.31381516,  4.        ],
       [ 0.48719547,  0.        ],
       [ 0.66057579,  6.        ],
       [ 0.83395611, 12.        ],
       [ 1.00733642, 18.        ],
       [ 1.18071674,  6.        ],
       [ 1.35409705,  1.        ],
       [ 1.52747737,  0.        ],
       [ 1.70085768,  1.        ],
       [ 1.874238  ,  1.        ],
       [ 2.04761832,  1.        ],
       [ 2.22099863,  1.        ],
       [ 2.39437895,  0.        ],
       [ 2.56775926,  1.        ],
       [ 2.74113958,  1.        ],
       [ 2.91451989,  0.        ],
       [ 3.08790021,  0.        ],
       [ 3.26128053,  0.        ],
       [ 3.43466084,  1.        ]])

我想用coords

例如上面的直方图中,解应该是这样的:

x= 0.48 处有一个 y=0 值。我想绘制解决方案的线并在 y=0.

时获取该线的 x 的值

在其他直方图中,解法是:

编辑

另一个测试解决方案的数据集示例:

i3s1=[1.4856339999999992, 0.27564800000000034, 1.1008430000000011, 1.2301969999999987, 0.2667920000000006, 0.8187089999999984, 0.42119200000000134, 0.5471469999999989, 1.0582640000000012, 0.7725049999999989, 0.8486200000000004, 0.8414530000000013, 0.34434200000000104, 3.3969810000000003, 4.355844999999999, 1.5555109999999992, 1.2929899999999996, 1.2005979999999994, 2.6386439999999993, 1.2733500000000006, 1.2238090000000028, 1.406841, 1.227254000000002, 1.4577429999999936, 1.204816000000001, 0.4409120000000044, 1.1166549999999944, 0.20276700000000147, 3.8218770000000006, 0.11855700000000269, 2.541343999999995, 0.0911790000000039, 2.0708699999999993, 2.6000489999999985, 0.11452600000000501, 0.16021299999999883, 2.288936999999997, 0.266489, 0.18775300000000072, 2.497996999999998, 0.42036200000000434, 2.3378999999999976, 0.23202399999999557, 2.6313650000000024, 0.20198899999999753, 0.17698099999999783]

使用具有负斜率的 itertools.combinations to get a list of all possible red lines and then find the linear function,该斜率具有 y=0 的最小 x 值。

import pandas as pd
from itertools import combinations

#get all possible combinations of points that a linear function should cross
all_combinations = pd.DataFrame(
        map(lambda r: (r[0][0], r[0][1], r[1][0], r[1][1]), 
            combinations(coords,2)),
    columns=["x1", "y1", "x2", "y2"])

#calculate a and b for each linear function using y=a*x+b
all_combinations["a"] = ((all_combinations["y2"] - all_combinations["y1"]) 
    / (all_combinations["x2"] - all_combinations["x1"]))
all_combinations["b"] = (all_combinations["y2"] - 
    all_combinations["a"] * all_combinations["x2"])

#for each linear function get the x value for y=0 (called x0)
all_combinations["x0"] = - all_combinations["b"] / all_combinations["a"]

#only keep the functions with a negative slope
neg_slope = all_combinations[(all_combinations["a"] < 0) & 
    (all_combinations["a"] != float("inf")) 
    & (all_combinations["a"] != float("-inf"))]

#only keep the function with the smallest x0
miny0 = neg_slope[neg_slope["x0"] == neg_slope["x0"].min()].reset_index()
x1, y1, x0 = miny0["x1"][0],miny0["y1"][0],miny0["x0"][0]

#plot the result
plt.bar(x=coords[:,0], height=coords[:,1],width=0.1)
plt.plot([x1, x0], [y1, 0], color="red")