Search code examples
pythonnumpymatplotlibgrapherrorbar

Python: Trying to plot error bars on a graph gives "ValueError: err must be [ scalar | N, Nx1 or 2xN array-like ]"


I've got the following problem when I try to plot error bars on my graph.

import numpy as np
import sys
import matplotlib.pyplot as plt

col1 = []
col2 = []
col3 = []

while True:
    try:

        N = input('Please enter the full name of your numbers text file with 
its file format (e.g "Numbers.txt"): ')
        with open(N, 'r') as f:
            for line in f:
                first, second, third = line.split()
                col1.append(first)
                col2.append(second)
                col3.append(third)


    except IOError:
        sys.exit('Error: Data file is invalid! Please ensure your file 
exists. ')    
    except ValueError:
        sys.exit('Error: Data file is invalid! Please ensure your file 
contains just numbers, as well as enough of them with none missing. ')       

    else:
        break
x = np.array(col1)
y = np.array(col2)
e = np.array(col3)

N = 1
p = 0

while N <= len(col1):
    p = p + 1/(float(col3[N-1]))**2
    N = N+1


N = 1
q = 0

while N <= len(col1):
    q = q + float(col1[N-1])/(float(col3[N-1]))**2
    N = N+1


N = 1
r = 0

while N <= len(col1):
    r = r + float(col2[N-1])/(float(col3[N-1]))**2
    N = N+1


N = 1
s = 0

while N <= len(col1):
    s = s + (float(col1[N-1]))**2/(float(col3[N-1]))**2
    N=N+1


N = 1
t = 0

while N <= len(col1):   
    t = t + (float(col1[N-1])*float(col2[N-1]))/(float(col3[N-1]))**2
    N = N+1


delta = (p*s)-(q**2)


a = ((r*s)-(q*t))/delta
b = ((p*t)-(q*r))/delta
print('a is equal to: ' + str(a))
print('b is equal to: ' + str(b))


sigma_a = float(s/delta)**0.5
sigma_b = float(p/delta)**0.5
print('Error in a (Sigma_a) is equal to: ' + str(sigma_a))
print('Error in b (Sigma_b) is equal to: ' + str(sigma_b))

best_y = []
best_x = col1
N = 0
while N <= len(col1)-1:
    Y = a + ((b)*(float(col1[N])))
    best_y.append(Y)
    N = N + 1
    Y = 0



plt.plot(x, y, 'ro', best_x, best_y)
plt.errorbar(x, y, yerr=e, fmt='-o')
plt.title('Graph to show relationship between given values of x and y')
plt.xlabel('x')
plt.ylabel('y')
plt.grid(True)
plt.show()

The output python gives is this:

"ValueError: err must be [ scalar | N, Nx1 or 2xN array-like ]"

What seems to be the problem?

By the way, the file used to provide the numbers is a txt file and is this:

-2      2.1     -0.365635756
0       2.4      0.347433737
2       2.5      0.263774619
4       3.5     -0.244930974
6       4.2     -0.004564913

Apologies for the large amount of code in this post but I feel that I should include anything that may be hiding the problem (still quite new to python).

Many thanks,

Luke.


Solution

  • You aren't converting the string values from the file into floats. This is why matplotlib is throwing the error. When you convert col1, col2, and col3 to arrays via np.array() it doesn't convert the string values into floats, it just creates arrays of strings (you can see this by examining x, y, or e like:

    In[1]: x
    Out[1]: 
    array(['-2', '0', '2', '4', '6'], 
          dtype='<U2')
    

    The dtype='<U2' indicates that the elements are unicode strings.

    The quickest way to fix your code is to explicitly convert the values to float when you read them append them to your column lists as shown here:

    while True:
        try:
    
            N = input('Please enter the full name of your numbers text file with 
    its file format (e.g "Numbers.txt"): ')
            with open(N, 'r') as f:
                for line in f:
                    first, second, third = line.split()
                    col1.append(float(first))
                    col2.append(float(second))
                    col3.append(float(third))
    

    A better fix would be to use the Python standard library csv module to handle the reading and parsing of your datafiles.