-1

I am trying to make a plot of column density, "nh", for a number of sources. Each source is represented by a key value. And I have multiple dictionaries that match that key to some value. For example:

print(nh_noUL_val, '\n')
print(noUL_colors, '\n')
print(asymetric_error,'\n')

This gives my data:

{2: 3.3e+21, 7: 7e+20, 29: 2e+22, 203: 8.5e+21, 226: 2.1e+21, 231: 6e+19, 259: 4.2e+21, 307: 1.8e+20, 320: 2.6e+21, 366: 4.4e+22, 374: 6e+21, 1143: 3e+22} 

{2: 'black', 7: 'green', 29: 'red', 203: 'blue', 226: 'blue', 231: 'blue', 259: 'blue', 307: 'green', 320: 'green', 366: 'blue', 374: 'red', 1143: 'red'} 

{2: [4e+20, 4e+20], 7: [7e+20, 3.6e+21], 29: [2e+22, 3.3e+22], 203: [8.5e+21, 2.47e+22], 226: [2.1e+21, 2.17e+22], 231: [6e+19, 9.76e+21], 259: [4.2e+21, 1.9899999999999997e+22], 307: [1.8e+20, 4.65e+21], 320: [2.6e+21, 1.2900000000000001e+22], 366: [4.4e+22, 1.4800000000000001e+23], 374: [6e+21, 3.1e+22], 1143: [3e+22, 4e+22]} 

With this data, I am trying to plot each source as a colored data point with its respective color, value, and asymmetric errors.

fig, ax = plt.subplots()

for x, y, yerr, color in zip(nh_noUL_val.keys(), nh_noUL_val.values(), asymetric_error.values(),
                             noUL_colors.values()):

    ax.errorbar(x,y , yerr = asymetric_error,  color = color, marker = 'o', ms = 5)
plt.show()

However, this gives me:

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

Admittedly, I am somewhat new to python and don't fully understand arrays. But my guess would be that my asymmetric_error.values() is actually an Nx2 array? If that's the case, how do I get that into 2xN form? If that's not the case, what is wrong with my code?

ZacharyC
  • 99
  • 1
  • 10
  • `.., asymetric_error.values(), colors.values()):` - should that be `...noUL_colors.values()):`? – wwii Jan 08 '20 at 03:33
  • yes, thanks! I changed the variable name and forgot to correct it later on. But the problem still remains. – ZacharyC Jan 08 '20 at 03:36
  • Where does that come up for you? If it wasn't defined, wouldn't printing it like I did not have worked. – ZacharyC Jan 08 '20 at 03:39

1 Answers1

2

You are passing a dictionary for the yerr parameter. It expects a scalar or array-like, shape(N,) or shape(2,N),

 ax.errorbar(x,y , yerr = asymetric_error,...

You want asymmetric bars so yerr needs to be shape(2,N) which means two items each with N values. Since you are plotting a single point at a time while iterating, N=1. yerr needs to be [[neg_error][pos_error]].

Your for statement needs to capture those two errors separately like this.

for x, y, (neg_err,pos_err), color in zip(nh_noUL_val.keys(), nh_noUL_val.values(),
                                          asymetric_error.values(), noUL_colors.values()):
    #print(x, y, yerr, color)
    ax.errorbar(x,y , yerr=[[neg_err],[pos_err]],  color=color,marker='o', ms=5)

One caveat. Your loop relies on the three dictionaries being in the same order. If you are using Python 3.7+ that isn't a problem if they wer constructed in the same order. If you are using 3.5- you will need to make sure the values from each dictionary are for the same key(s). Something like this:

for x,y in nh_noUL_val.items():
    color = noUL_colors[x]
    neg, pos = asymetric_error[x]
    ax.errorbar(x,y,yerr=[[neg],[pos]],color=colors,marker='o', ms=5)
wwii
  • 23,232
  • 7
  • 37
  • 77
  • So for example if one dictionary had my keys ordered as `[2,3,5,7]` and another was ordered as `[2,5,7,3]`, then it wouldn't work correctly? – ZacharyC Jan 08 '20 at 04:41
  • @ZacharyC The way you wrote your for loop using `.keys()` and `.values()` you are relying on Python v3.7+ **and** that all three dictionaries were created with the same *insertion* order. - [Are dictionaries ordered in Python 3.6+?](https://stackoverflow.com/questions/39980323/are-dictionaries-ordered-in-python-3-6) - in 3.6 it was an implementation detail starting 3.7 it was guaranteed. Prior to 3.6 to get the same behaviour you had to use a [`collections.OrderedDict`](https://docs.python.org/3/library/collections.html#collections.OrderedDict). – wwii Jan 08 '20 at 15:42