简体   繁体   中英

Python how to know which 3 points are a line

I've found some solutions using the triangle area to find lines but It's not what I need because in further steps will not be a solution for my problem.

I've been working on a nested loop where I see the slope between point 0 and 1 and gives me a projection for next points (expexcted price for each point) If the price is the same +- tolerance I have found a line.

Now I've the first loop returning me Slopes but I'm struggling with the second loop to get the exp_price comparision... Any idea on how to find this lines simple?


initial_data = {'index': [4, 17, 24, 36, 42],
    'High': [805.000000, 1094.939941, 1243.489990, 1201.949951, 1172.839966],
}
test = pd.DataFrame(initial_data)

slope_data = {'index': [4, 17, 24, 36, 42],
    'High': [805.000000, 1094.939941, 1243.489990, 1518.7, 1172.839966],
    'Slope': [0, 22.30307, 21.22144, 22.93417, -57.64334],
}

The nested loop is an option, but maybe is an easiest way vecotrizing to know which 3 are a line?

for i in range(len(test)):
    #test.loc[:,'slope'] = (test.loc[i,'High'] - test.loc[i,'High'])   / (test.loc[i,'index'] - test.loc[i,'index'])
    test['slope'] = round((test['High']-test['High'].shift(1)) / (test['index']-test['index'].shift(1)),8)
    print(test)

    for j in range(len(test)):
         exp_price = (test['High'].shift(1) + (test['slope']*(test['index']-test['index'].shift(j))))
         #If exp_price of j equals High of i  (+- 0,5% tolerance) I've found a line!

         # print(values)

    test['result'] = values
    print(test)

Note I want to compare 0,1 with 2, 3 and 4.

0, 2 with 3, 4.

0, 3 with 4.

1, 2 with 3, 4.

and so on... That's why I try to use the nested loop.

You can do this:

coords = list(zip(test['index'], test.High))
slope = pd.DataFrame([[(coly - rowy)/(colx - rowx) if colx > rowx else None for colx, coly in coords] for rowx, rowy in coords], columns=coords, index=coords)
pointsAndCandidate = [(i, j, k) for i in range(len(test.index) - 2) for j in range(i + 1, len(test.index) - 1) for k in range(j + 1, len(test.index))]
df3 = pd.DataFrame(columns=[
    'linex','liney','candx','candy', 'slope'], index = pointsAndCandidate, data = [
    (*coords[row[1]], *coords[row[2]], slope.iloc[
    row[0], row[1]]) for row in pointsAndCandidate])
df3['projy'] = df3.liney + df3.slope * (df3.candx - df3.linex)
df3['inline'] = (df3.candy / df3.projy - 1).abs() < 0.01
print(df3)

Output:

           linex        liney  candx        candy      slope        projy  inline
(0, 1, 2)     17  1094.939941     24  1243.489990  22.303072  1251.061448    True
(0, 1, 3)     17  1094.939941     36  1201.949951  22.303072  1518.698316   False
(0, 1, 4)     17  1094.939941     42  1172.839966  22.303072  1652.516751   False
(0, 2, 3)     24  1243.489990     36  1201.949951  21.924500  1506.583984   False
(0, 2, 4)     24  1243.489990     42  1172.839966  21.924500  1638.130981   False
(0, 3, 4)     36  1201.949951     42  1172.839966  12.404686  1276.378067   False
(1, 2, 3)     24  1243.489990     36  1201.949951  21.221436  1498.147217   False
(1, 2, 4)     24  1243.489990     42  1172.839966  21.221436  1625.475830   False
(1, 3, 4)     36  1201.949951     42  1172.839966   5.632106  1235.742586   False
(2, 3, 4)     36  1201.949951     42  1172.839966  -3.461670  1181.179932    True

Explanation:

  • Create a dataframe containing the slopes of pairs of interest in the upper diagonal
  • Create a list of all index combinations of interest: point1, point2, candidate ; for the example in the question, this is (0,1,2), (0,1,3), (0,1,4), (0,2,3), (0,2,4), (0,3,4), (1,2,3), (1,2,4), (1,3,4), (2,3,4)
  • Create a dataframe with columns linex, liney, candx, candy, slope which are the x, y coords of one of the points on the line, the coords of the candidate point, and the slope of the line
  • Add to it the column projy which is the projected y coord for the candidate's x coord, and also the column inline which indicates whether candy matches projy within a given tolerance, meaning the candidate is indeed collinear with the two points.

Intermediate results:

test
   index         High
0      4   805.000000
1     17  1094.939941
2     24  1243.489990
3     36  1201.949951
4     42  1172.839966
coords
[(4, 805.0), (17, 1094.939941), (24, 1243.48999), (36, 1201.949951), (42, 1172.839966)]
slope
                  (4, 805.0)  (17, 1094.939941)  (24, 1243.48999)  (36, 1201.949951)  (42, 1172.839966)
(4, 805.0)              None          22.303072         21.924500          12.404686           9.679999
(17, 1094.939941)       None                NaN         21.221436           5.632106           3.116001
(24, 1243.48999)        None                NaN               NaN          -3.461670          -3.925001
(36, 1201.949951)       None                NaN               NaN                NaN          -4.851664
(42, 1172.839966)       None                NaN               NaN                NaN                NaN
pointsAndCandidate
[(0, 1, 2), (0, 1, 3), (0, 1, 4), (0, 2, 3), (0, 2, 4), (0, 3, 4), (1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]
result
           linex        liney  candx        candy      slope        projy  inline
(0, 1, 2)     17  1094.939941     24  1243.489990  22.303072  1251.061448    True
(0, 1, 3)     17  1094.939941     36  1201.949951  22.303072  1518.698316   False
(0, 1, 4)     17  1094.939941     42  1172.839966  22.303072  1652.516751   False
(0, 2, 3)     24  1243.489990     36  1201.949951  21.924500  1506.583984   False
(0, 2, 4)     24  1243.489990     42  1172.839966  21.924500  1638.130981   False
(0, 3, 4)     36  1201.949951     42  1172.839966  12.404686  1276.378067   False
(1, 2, 3)     24  1243.489990     36  1201.949951  21.221436  1498.147217   False
(1, 2, 4)     24  1243.489990     42  1172.839966  21.221436  1625.475830   False
(1, 3, 4)     36  1201.949951     42  1172.839966   5.632106  1235.742586   False
(2, 3, 4)     36  1201.949951     42  1172.839966  -3.461670  1181.179932    True

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM