AttributeError: 'list' object has no attribute 'tolist' Sea Level Predictor

Hi, everyone!

I have come across this error while testing the Sea Level Predictor assignment:

`ERROR: test_plot_lines (test_module.LinePlotTestCase)

Traceback (most recent call last):
File “/home/runner/boilerplate-sea-level-predictor/test_module.py”, line 33, in test_plot_lines
actual = self.ax.get_lines()[0].get_ydata().tolist()
AttributeError: ‘list’ object has no attribute ‘tolist’`

It seems that the test module retrieves a list by assigning actual to self.ax.get_lines()[0].get_ydata() and it is impossible to apply tolist() function to it. But I have no idea why this happens.

Here’s my repl:

I’ll be glad for any help.

I have investigated this error some more. I found out that the get_ydata() function retrieves a list of 2 values: [0 , 1]

The test_module expects a list of many more values. I still don’t understand as the function get_lines() returns 2 x 2D lines. It seems that get_ydata() doesn’t retrieve all the values from those lines. Anybody knows why?

I’m having the same error too and I can’t figure out why it’s happening

Same problem. At this point I might suspect the boilerplate code expects a different way to plot the lines with slope and y_intercept parameters?

I used ‘ax.axline’ and it worked perfectly. Too bad I’m still getting this error…

I spent several hours debugging this (and re-re-re- re-learning pandas/matplotlib) and I finally understood what is happening (in my case).
Please bear with me (Replit link at the end):

As mentioned before, I understood from the problem that we’re supposed to plot the trend lines using a slope value and Y -intercept value. So, the most straightforward approach was to use ‘axline’. Unfortunately the boilerplate code checks for a different approach, using ‘plt.plot’ instead. The test_module will check the arrays for the X and Y values provided in the function.

The object passed to this test_module function by ‘axline’ (or whatever you’re using) is incorrect. Giving your error.

If you switch to ‘plt.plot()’ it will work. BUT, it yielded a new set of problems (instead of ERROR we now get FAIL). This is where I took most of my time to solve this.

Now, the values I was giving to plot the line with ‘plt.plot()’ were incompatible with the expected values. I was using the DataFrame + 1 additional point (2050, regression result) or (2050, NaN) to get the regression lines to go to 2050. So graphically it was correct, but NOW the test_module would indicate that the array ‘len()’ was shorter than it was expected (134 items vs. 171 items). The numerical values were correct, though. Check both!

After a couple of hours (lol) I figured out that 171 - 134 = 37 items. That’s the exact amount of data points missing from 2013 (last data point in the DataFrame) to 2050! So, the boilerplate code is asking you to fill the DataFrame with the remaining data points, using your regression equations!

So, after I plot the scatter plot, I modify the data frames (I made a copy for the one with values above Year 2000) to include said points by passing a Dictionary to ‘pd.concat()’ (pd.append() is deprecated and was removed from Pandas) where the keys are ‘Year’ and ‘CSIRO Adjusted Sea Level’, and the values are lists containing the years [2014 - 2050] and the associated values, calculated from the slope and Y-intercepts of both regression lines (y = ax+b → value = slope * date + Y-intercept). For that I used a simple for loop with the years as range.

It was extremely convoluted (instead of ‘ax.axline’) BUT it was what yielded the correct result in my case.

I hope that what I said here is enough for you to resolve your problems!
You can find my code here

PS: Don’t know why the legend is messed up. It doesn’t happen in VSCode.

2 Likes

People, I have just solved.
The thing is…

The results expected in
self.ax.get_lines()[0].get_ydata().tolist() and
self.ax.get_lines()[1].get_ydata().tolist()
are exactly the y values for y = slopex + y-intercept (or y = ax + b) but for certain points.

Also, the first one expected a list where x comes from 1880 to 2050 (one by one) [I just used range() here], and the second one from 2000 to 2050.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.