如何找到所有负斜率直线并获得最小 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
到
- 计算所有负斜率的直线
- 得到最小 y=0 值的那个
- 在直方图上画出这条线,
- 获取该行的y=0的x轴值
例如上面的直方图中,解应该是这样的:
在 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")
我想实现一个绘制直方图的函数,并计算使用 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
到
- 计算所有负斜率的直线
- 得到最小 y=0 值的那个
- 在直方图上画出这条线,
- 获取该行的y=0的x轴值
例如上面的直方图中,解应该是这样的:
在 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")