0

Dear Stackoverflow users,

How does one show the equation of a trendline made using the python module scipy? Considering that it might not be possible to do that so easily. How can i calculate the slope and intersection point so i can program it myself?

Figure 1: measurement of a yet unknown noise color

import pandas as pd
import matplotlib.pyplot as plt
import TISTNplot as tn
import numpy as np
from scipy import optimize

path = "removed for privacy reasons"
metingen = ['A', 'B', 'C', 'D', 'E', 'F']

"""
Gebruikte kleurcodes behorende bij de geluidskleur
"""
blauw = '#0066ff'   # 3dB/octaaf
grijs = '#cbcbcb'   # a-weging
roze = '#ff66cc'    # -3dB/octaaf
bruin = '#663300'   # -6dB/octaaf
violet = '#9900ff'  # 6dB/octaaf
wit = '#aa0000'     # 0dB/octaaf
zwart = '#000000'

kleur = [blauw, roze, bruin, grijs, violet, wit]

i = 0
meting = metingen[i]
df = pd.read_csv(path+meting+'.txt', sep='\t', header=None, names=['freq', 'intense'], decimal=",")

x = df['freq']
y = df['intense']
x1 = x[df['freq'] < 11][df['freq'] > 8]
y1 = y[df['freq'] < 11][df['freq'] > 8]

print(x1)

plt.plot(x, y, '.', label="Bestand: %s" % metingen[i], color=kleur[i], ms=2)
plt.plot(x1, y1, '.', label="Bestand: %s" % metingen[i], color=kleur[i], ms=5)

"""
Functie voor de trendlijn.
In dit geval een lineaire lijn.
"""
def theorie(x, a, b):
    """ x moet een np.array zijn """
    return a*x+b

params = [0, 2]  # begin waarde voor de fit

params, covariance = optimize.curve_fit(theorie, x1, y1, params)
plt.plot(x, theorie(x, *params), '-b', label='trendlijn', color='red')


"""
Zorgt voor de correcte opmaak
"""
tn.PRECISION_X = 5
tn.PRECISION_Y = 5
tn.fix_axis(plt.gca())
plt.tight_layout()
plt.legend(loc=0)
#plt.xlim(8, 13)
plt.grid()
plt.show()

You're seeing code that reads datafiles. The data has a large uncertainty outside the 8-11 x-axis range. That's why the trend line is fitted in that area.

I'll be happy to receive any feedback on this problem.

Kind regards

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
BDK
  • 5
  • 1
  • 5

2 Answers2

0

You can use np.polyfit() to fit data to a line (see here). A linear trendline would be a 2nd degree polynomial (y = mx + b). That will return a numpy array with the coefficients of the polynomial, which you can use np.linspace() and np.poly1d() to make a numpy array and plot in matplotlib just like you'd plot the other two lines you have above. More details in the link provided.

halp_me
  • 46
  • 7
  • Firstly i would like to say that i appreciate your answer. However this is not the answer to my question. – BDK Mar 23 '17 at 19:53
  • Sorry about that. Let me ask a clarifying question: Do you want to write code to do the polynomial fit code yourself? – halp_me Mar 23 '17 at 19:56
  • FYI, if you _don't_ want to code it yourself, there's an example of the solution I suggested [here](https://stackoverflow.com/questions/19068862/how-to-overplot-a-line-on-a-scatter-plot-in-python/19069001#19069001) – halp_me Mar 23 '17 at 20:00
  • Oh! I understand your question! Sorry for not reading carefully enough. If you use `np.polyfit()` as suggested, you get `m` and `b`. With those you can use `plt.text()` to add a string to your plot. So like `plt.text(2, 0.65, 'y = {} x + {}'.format(m, b)`. See more examples of text on plots [here](http://matplotlib.org/gallery.html#text_labels_and_annotations). – halp_me Mar 23 '17 at 20:08
  • Okay great! Is this also possible with scipy? As this is what our professor encourages us to use over numpy for this function. – BDK Mar 23 '17 at 20:19
  • The only thing I can find that's strictly in the `scipy` package is `optimize.curve_fit()` which it looks like you're already using. SciPy is a whole "ecosystem" which [includes numpy](https://scipy.org/). But I think if you want to do your fitting within the `scipy` package, the solution you have is correct. – halp_me Mar 23 '17 at 20:28
0

Problem has been solved!

params, covariance = optimize.curve_fit(lineair, x1, y1, params)

params returns the slope and intersection point.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
BDK
  • 5
  • 1
  • 5