3

I'm trying to fit and plot a simple data in a .txt file with a linear function (a*x+b) using matplotlib and scipy. I run into an error concerning the test function: "can't multiply sequence by non-int of type 'numpy.float64'"

I have tried changing the variable name x but I get the same problem. Most of the code comes from a working one that is able top fit data without problems and uses the same definition for the test function.

import matplotlib.pyplot as plt
from scipy import optimize
import numpy as np
f=open("testData.txt","r")
x_data=[]
y_data=[]
trash=f.readline() #discards first line
for line in f: #reads x and y data from file
    x_read,y_read=line.split()
    x_data.append(float(x_read))
    y_data.append(float(y_read))

def test_func(x, a, b):
    return a*x+b

params, params_covariance = optimize.curve_fit(test_func, x_data, y_data, 
p0=[1, 1])
plt.figure(figsize=(6, 4))
plt.scatter(x_data, y_data)
plt.plot(x_data, test_func(x_data, params[0], params[1]), label='Fitted 
function')
plt.show()

This is the error :

Traceback (most recent call last):

File "C:/Users/Fra/Desktop/lab/ottica/2/reaqd.py", line 19, in plt.plot(x_data, test_func(x_data, params[0], params[1]), label='Fitted function')

File "C:/Users/Fra/Desktop/lab/ottica/2/reaqd.py", line 14, in test_func return a*x+b

TypeError: can't multiply sequence by non-int of type 'numpy.float64'

Arkistarvh Kltzuonstev
  • 6,824
  • 7
  • 26
  • 56

2 Answers2

6

You're probably trying to multiply a Python list by a float, which does not work. Try a*np.array(x)+b

Jussi Nurminen
  • 2,257
  • 1
  • 9
  • 16
  • Thanks, it worked. I don't quite get why it works, shouldn't the "x" variable behave like a float? – Francesco Pettini Apr 18 '19 at 08:56
  • @FrancescoPettini no, in your code `x` is a Python list. Multiplication of Python lists by floats is not defined, since they can contain arbitrary objects (not just numbers). – Jussi Nurminen Apr 18 '19 at 09:24
  • Note that this is slower than changing the initial list into a numpy array directly, before fitting and plotting. Now, every time the function is called, the list is changed into a NumPy array, with all the overhead. For hard (read: slow) to fit functions and large lists, this may slow down things noticeably. – 9769953 Apr 18 '19 at 10:08
0

As you are asking about how the accepted answer works, showing the "old-school" way may have its use:

plt.plot(x_data, 
  [test_func(x, params[0], params[1]) for x in x_data],
  label='Fitted function')

x_data = [] is clearly a list, and as Python is not Matlab, number*x_data is not an element-wise multiplication, but creates a list which repeats x_data, number times, which needs an integer.

tevemadar
  • 12,389
  • 3
  • 21
  • 49