0

I have a set of data from a pd.DataFrame which looks like this, with a 3rd-order polynomial fitted to it:

enter image description here which is fit by

# Find the 3rd-order polynomial which fits the SED
coefs = poly.polyfit(x, y, 3) # find the coeffs
x_new = np.linspace(lower, upper, num=len(x)*10) # space to plot the fit
ffit = poly.Polynomial(coefs) # find the polynomial

How could I find the straight line that fits only part of the data, for example, just the downward slope within 9.5 < x < 15 ?

I could slice the dataframe into pieces with

left = pks[pks[xvar] < nu_to]
right = pks[pks[xvar] > nu_to]

but I'd like to avoid that, since I'll have to do the same thing with many datasets.

This question is about MatLab This current question is a distillation of my previous one.

Jim421616
  • 1,434
  • 3
  • 22
  • 47
  • The answer depends on the amount of high frequency variations in your dataset. My first suggestion would be to put 0 in second and third coefficients. Can you plot the results? – user3435121 Oct 23 '22 at 21:58
  • Perhaps I wasn't clear. My confusion lies not in what the coefficients should be, but in how to restrict the straight line to a range of x values. – Jim421616 Oct 23 '22 at 23:41
  • Does this answer your question? [Finding two linear fits on different domains in the same data](https://stackoverflow.com/questions/74147461/finding-two-linear-fits-on-different-domains-in-the-same-data) – JJacquelin Oct 24 '22 at 08:01
  • No, because that's also my question. I'll edit this one to make that clear. – Jim421616 Oct 24 '22 at 21:13

2 Answers2

0

Assuming the curve shape is always going to be similar to the example, you could fit a line to the portion of your dataset limited by the ymax and ymin values. You could automate the detection of that subset by calculating the y range between the ymax and ymin values, as well as the corresponding x values. The use of the min and max inside the slice is to take into account the min and max values of y might not always be in the same order:

linearx = x[min(np.argmax(y), np.argmin(y)): max(np.argmax(y), np.argmin(y))+1]
lineary = y[min(np.argmax(y), np.argmin(y)): max(np.argmax(y), np.argmin(y))+1]
Carlos Melus
  • 1,472
  • 2
  • 7
  • 12
0

Maybe you just use the linear part of your polynomial fit. The idea is to get slope and offset by first eliminating the quadratic term. Say you have

y = a x^3 + b x^2 + c x + d,

setting x -> x - b / 3a removes the quadratic term. The remaining function has a linear slope of

c' = c - b^2 / 3a

and an offset of

d'= d-b c / 3a + 2b^3 / 27a^2.

Transforming the linear part back gives you the final offset

d'' = d - b^3/ 27a^2

so the linear part is given by

y = ( c - b^2 / 3a ) x + d - b^3/ 27a^2

mikuszefski
  • 3,943
  • 1
  • 25
  • 38