Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

"ValueError: x and y must be the same size" when plotting with matplotlib

I’m writing a python code that implements euler’s method to solve a 1st order ODE for an arbitrary range of values of time-step h.

The simplest solution i’ve come up with is to declare a Python list to store the results at the end of the ‘outer for’ loop:

y = []

for h in (0.05, 0.1, 0.2):
    t = np.arange(0, 5 + h, h) ## Time-steps as np array

    N = np.zeros(len(t)) ## Initialize number of U^{235} nuclei array.
    N[0] = N_0

    ## Implementation of Euler's method, first-order case. One 'for' loop suffices.
    for i in range(0, len(t) - 1):
        N[i+1] = N[i] * (1.0 - h/tau)
    
    y.append(t) ## Store results in python list. Each element is an array
                ## with the corresponding value of h

Then I tried to plot the results for h = 0.05, that are stored in y[0], as x-axis:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

plt.scatter(y[0], N, marker='o', facecolors='none', s=60, lw=2)

But this returns the error "ValueError: x and y must be the same size"

I don’t understand why I’m getting size error. Isn’t y[0] an one-dimensional list? So i can’t use a list as an axis for a plot?

I’m confused because it WORKS with the variable t as it is a np.array:

t = np.arange(0, 5 + h, h) ## Time-steps as np array

    N = np.zeros(len(t)) ## Initialize number of U^{235} nuclei array.
    N[0] = N_0

    ## Implementation of Euler's method, first-order case. One 'for' loop suffices.
    for i in range(0, len(t) - 1):
        N[i+1] = N[i] * (1.0 - h/tau)


plt.scatter(t, N, marker='o', facecolors='none', s=60, lw=2)

>Solution :

You are not storing the various N arrays in a list, so you are trying to plot t from the first iteration (i.e. y[0]) and N from the last iteration.

If you store everything in a dictionary, you can store the time and the number of nuclei as a value and the time increment h as a key:

# Imports.
import matplotlib.pyplot as plt
import numpy as  np

# Constants.
N_0 = 1000
TAU = 5
TIME_INCREMENTS = (0.05, 0.1, 0.2)

data = {}
for h in TIME_INCREMENTS :
    t = np.arange(0, 5 + h, h) # Time-steps as np array.
    N = np.zeros(len(t)) # Initialize number of U^{235} nuclei array.
    N[0] = N_0
    # Implementation of Euler's method, first-order case. One 'for' loop suffices.
    for i in range(0, len(t) - 1):
        N[i+1] = N[i] * (1.0 - h/TAU)    
    data[h] = (t, N)
  
fig, ax = plt.subplots()
for key, values in data.items():
    ax.scatter(*values, marker='o', s=60, lw=2, label=f"h = {key:.2f}")
ax.legend()

enter image description here

When you use numpy, you want to avoid loop for performance reasons (say if you have 1M of time increments). We could turn this:

N = np.zeros(len(t))
N[0] = N_0
for i in range(0, len(t) - 1):
    N[i+1] = N[i] * (1.0 - h/TAU) 

Into this:

N = N_0 * (1.0 - h/TAU)**np.arange(len(t))
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading