Newcomer to Jupyter Lab, Conda, and Matplotlib here.
So I'm running into the weirdest problem.
Here's the background: my program uses polyfit()
to find a line of best fit for 30 randomly generated points. The points were randomly generated using a target function. I first used a polyfit line of degree 1 (just a line), and then I used a polyfit line of degree 3 to better approximate the target function using the randomly generated points. I got the random points generated, the target function, and the two polyfit functions to work just fine, and it even plotted in Jupyter Lab.
Here's the problem: After closing the .ipynb file that I was working on. I opened it back up using Ubuntu's file explorer (while the Jupyter Lab instance was still running). I made some changes to my program, and now it won't plot anymore. plt.scatter()
still scatterplots just fine, but plt.plot()
doesn't display the functions on my graph. I don't get any warning messages of any sort or any interpreter errors. Right now, I can see two possible causes:
I messed up something when I closed the .ipynb file and reopened it in file explorer while Jupyter Lab instance was still running. Some poking around on here revealed that other users had vaguely similar problems, and the issues were caused by the environment not being linked anymore? I checked and my (base) Conda environment has matplotlib installed. This may or may not be the cause, but I figured it was worth mentioning to assist with troubleshooting.
The second, and more mundane, reason is that I simply messed something up in my program (I am a relative beginner to Python, so this is entirely possible). I've tried to debug the program myself, but with no warning or error messages, it is hard to know where to start. My print()
statements are showing the variables to be in the correct type (either as arrays/lists or floats).
Here is my program (it's an .ipynb file). All helpful suggestions are much appreciated. Thank you!
import numpy as np
import matplotlib.pyplot as plt
import random
import warnings
# warnings.filterwarnings("ignore")
def func(x):
return x**3 + 2 * x**2 - 5 * x - 6
def line(x):
return slope * x + y_int
def third_poly(x):
return poly_trans[0] * x**3 + poly_trans[1] * x**2 + poly_trans[2] * x + poly_trans[3]
num_of_data_points = 30
x = np.linspace(-4.0, 4.0)
x_values = []
y_values = []
for i in range(num_of_data_points):
x = np.random.uniform(-4.0, 4.0)
y = np.random.uniform(-2.0, 2.0)
fx = func(x) + y
plt.scatter(x, fx)
x_values.append(x)
y_values.append(fx)
lin_reg = np.polyfit(x_values, y_values, 1)
# lin_reg is an array of size 1x2, first element is the coefficient, second element is the y-int
poly_trans = np.polyfit(x_values, y_values, 3)
print(lin_reg)
print(lin_reg.shape)
print(poly_trans)
print(poly_trans.shape)
y_int = lin_reg.flat[1]
slope = np.delete(lin_reg, 1)
print(y_int)
print(y_int.shape)
print(slope)
print(slope.shape)
plt.plot(x, func(x), label = "Target function (f(x))")
plt.plot(x, line(x), label = "Line of best fit (g)")
plt.plot(x, third_poly(x), label = "3rd-Order Polynomial transformation (g')")
plt.legend(loc = "upper left")
plt.ylim(-45, 50)
plt.xlim(-5, 5)
plt.grid()
plt.show()
You have a small semantic error, where you are plotting the functions with respect to x
which is a single datapoint. You should plot them with x_values
. Additionally, the plotting within the for loop is counter-productive, since this will be treating every new scatter plot as a new group (hence the different colours).
Here's a better version:
# Define the target function
def targetFunction(x): # Define the target function f(x)
return x**3 + 2 * x**2 - 5 * x - 6
# Define the line function
def lineFunction(x, slope, yIntercept): # Define the line function g(x)
return slope * x + yIntercept
# Define the third degree polynomial function
def thirdPolyFunction(x, polyTransform): # Define the 3rd degree polynomial function g'(x)
return polyTransform[0] * x**3 + polyTransform[1] * x**2 + polyTransform[2] * x + polyTransform[3]
# Generating data points
numOfDataPoints = 30
xValues = [] # Initialize list to store x values
yValues = [] # Initialize list to store y values
for i in range(numOfDataPoints): # Loop for generating random data points
x = np.random.uniform(-4.0, 4.0) # Generate random x value within range
y = np.random.uniform(-2.0, 2.0) # Generate random y value within range
fx = targetFunction(x) + y # Compute y value based on target function and random noise
xValues.append(x) # Append x value to the list
yValues.append(fx) # Append y value to the list
# Regression and sorting
linReg = np.polyfit(xValues, yValues, 1) # Perform linear regression
yIntercept = linReg[1] # Extract y-intercept from linear regression
slope = linReg[0] # Extract slope from linear regression
polyTransform = np.polyfit(xValues, yValues, 3) # Perform polynomial transformation
sortedIndices = np.argsort(xValues) # Get indices that would sort the x values
sortedX = np.array(xValues)[sortedIndices] # Sort x values in ascending order
sortedY = np.array(yValues)[sortedIndices] # Sort y values corresponding to sorted x values
# Plotting
plt.figure()
plt.scatter(sortedX, sortedY) # Plot the sorted data points
plt.plot(sortedX, targetFunction(sortedX), label="Target function f(x)") # Plot the target function
plt.plot(sortedX, lineFunction(sortedX, slope, yIntercept), label="Line of best fit (g)") # Plot the line of best fit
plt.plot(sortedX, thirdPolyFunction(sortedX, polyTransform), label="3rd-Order Polynomial transformation (g')") # Plot the polynomial transformation
plt.legend(loc="upper left") # Add legend to the plot
plt.ylim(-45, 50) # Set y-axis limits
plt.xlim(-5, 5) # Set x-axis limits
plt.grid() # Add grid lines to the plot
plt.title("Data Points, Target Function, and Fitted Models") # Add title to the plot
Also, I can recommend using the following imports:
import numpy as np
%matplotlib notebook
import matplotlib.pyplot as plt
%matplotlib notebook
is very nice since it enables interactive plotting. Hope this helps!
The results: