Search code examples
pythonnumpylinecurve-fitting

How to fit line of best fit to curve without multipolyfit or is there an alternate method


I found a question on here (Multivariate (polynomial) best fit curve in python?) which I believe would answer my question (I don't have any experience with curve fitting but I know my raw data will pretty much always be of this shape) but I cannot get multipolyfit installed fully. I have used 'pip install myltipolyfit' which worked, but when I run this script I get a traceback saying

Traceback

"from core import multipolyfit, mk_model, mk_sympy_function
ModuleNotFoundError: No module named 'core'"

I would like to know how others installed multipolyfit.

Code

import os
import csv
import pandas as pd
print('\n'*2)
import re
import matplotlib
import multipolyfit as mpf
from matplotlib.figure import Figure
from matplotlib import style
import numpy as np
import math
import matplotlib.pyplot as plt
from matplotlib.legend_handler import HandlerLine2D
from scipy.stats import linregress

x = [190,195,200,205,210,215,220,225,230,235,240,245,250,255,260,265,270,275,280,285,290]
av_50 = [5.045, 5.05, 5.115, 5.23, 5.355, 5.42, 5.59, 5.77, 5.855, 5.8, 5.745, 5.725, 5.795, 5.835, 5.81, 5.73, 5.675, 5.65, 5.63, 5.555, 5.405]

def min_max_values(num_list):
    results_list = sorted(num_list)
    return results_list[0], results_list[-1]

min_x, max_x = min_max_values(x)

# Plotting
plt.axis([min_x - 5, max_x + 5, 0, 8])

x = np.array(x)
y = np.array(av_50)
plt.plot(x, y, 'kx')

stacked_x = numpy.array([x,x+1,x-1])
coeffs = mpf(stacked_x, y, deg) 
x2 = numpy.arange(min(x)-1, max(x)+1, .01) #use more points for a smoother plot
y2 = numpy.polyval(coeffs, x2) #Evaluates the polynomial for each x2 value
plt.plot(x2, y2, label="deg=3")

plt.show()

Alternate method which works

from numpy import arange
from pandas import read_csv
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt



# define the true objective function
def objective(x, a, b, c):
    return a * x + b * x**2 + c
 
sclk = [190,195,200,205,210,215,220,225,230,235,240,245,250,255,260,265,270,275,280,285,290]
av_50 = [5.045, 5.05, 5.115, 5.23, 5.355, 5.42, 5.59, 5.77, 5.855, 5.8, 5.745, 5.725, 5.795, 5.835, 5.81, 5.73, 5.675, 5.65, 5.63, 5.555, 5.405]


# curve fit
popt, _ = curve_fit(objective, sclk, av_50)

# summarize the parameter values
a, b, c = popt
print('y = %.5f * x + %.5f * x^2 + %.5f' % (a, b, c))

# plot input vs output
plt.scatter(sclk, av_50)

# define a sequence of inputs between the smallest and largest known inputs
sclk_line = arange(min(sclk), max(sclk), 1)

# calculate the output for the range
av_50_line = objective(sclk_line, a, b, c)

# create a line plot for the mapping function
plt.plot(sclk_line, av_50_line, '--', color='red')
plt.show()

Solution

  • The multipolyfit package on PyPI is likely for Python 2, from a brief glance at its code.

    You may have more luck (when using Python 3; I do not recommend you use Python 2) when installing it directly from its repository page on GitHub:

    pip install https://github.com/mrocklin/multipolyfit.git --force-reinstall
    

    (--force-reinstall to overwrite your current installation). From a look at the code over there, at least the import there seems to be compatible with Python 3.

    The package, however, is seven to eight years old. It may still have other incompatibilities with current Python versions, and it is unlikely that these will be fixed by the author, given the lack of activity over the past years.

    So if you have working code that works without multipolyfit, that may be preferred.