PyPlot Bar chart shows non-existent values?

Viewed 75

I need some help with a pyplot bar chart that isn't doing what it should, and I cannot figure out why.

So basically what I need to do is draw the power function of a binomial distribution test. First I plot the binomial distribution and mark important values.

from scipy.stats import binom
import numpy as np
import matplotlib.pyplot as plt

n = 20
p = 1/2
x_values = list(range(n + 1))
prob = [binom.pmf(x, n, p) for x in x_values ]

cumult = 0
index_count = 0
for px in prob:
    cumult += px
    print(cumult)
    if cumult > 0.1:
        print(index_count-1)
        break
    else:
        index_count = index_count + 1

plt.bar(x_values,prob)
plt.axvline(x=6, color='red', linestyle='-', label='Grenze')
plt.axhline(y=0.1, color='green',linestyle='--',label='Signifikanzniveau')
plt.legend()
plt.show()

Binomial distribution plot
enter image description here

So far so good. Looks exactly like it should. Now for the power function what I do is add up the single probabilities from prob, and for each one, I calculate their probability of failing the test. Now the graph for this should look something like this for example

Example Graph enter image description here (ofc as a bar chart in my case)

Yet, my code

p_values = []
err_p = []
cumul = 0
for p in prob:
    cumul = cumul + p
    p_values.append(cumul)
    err_p.append(1-cumul)
 
    
x_pos = np.arange(len(p_values))
plt.bar(p_values, err_p)
plt.axvline(x=0.5, color='red', linestyle='-', label='p0')
plt.axhline(y=0.1, color='green',linestyle='--',label='Signifikanzniveau')
plt.legend()
plt.show()

Produces this weird bar chart
enter image description here which has values in the negatives and over 1 on the x-axis even though there are no values like this in the data??? I know that it worked once before I marked the values in this chart as well, but I haven't been able to reproduce it. I always get the one with non-existent values. I also don't know if it may have to do with the weirdly wide bars since in the first graph they look normal but here they sort of flow into each other.

1 Answers

For your task, you don't want to use a bar plot but a step plot:

plt.step(x=p_values, y=err_p, where="mid", label="err")
plt.axvline(x=0.5, color='red', linestyle='-', label='p0')
plt.axhline(y=0.1, color='green',linestyle='--',label='Signifikanzniveau')
plt.legend()
plt.show()

Sample output:

enter image description here

Bars have usually a constant width, hence they will leak into x-data that are not actually in your dataset. You could manually calculate the necessary width of each bar but thankfully matplotlib has implemented the step function for this task.

If you wanted a filled plot like a histogram, you could use fill_between:

plt.fill_between(x=p_values, y1=err_p, step="mid", color="lightblue", label="err")
plt.axvline(x=0.5, color='red', linestyle='-', label='p0')
plt.axhline(y=0.1, color='green',linestyle='--',label='Signifikanzniveau')
plt.legend()
plt.show()

Sample output:

enter image description here

Related