0

Below i have a code for the barplot, I would also like to show the Pvalue significane for these plots. Is there any easy way to indicate the statistical significance for these bars

import matplotlib.pyplot as plt

X= [-0.9384815619939103, 1.0755888058123153, 0.061274066731665564, 0.65064830688728]
x_labels = ['A' ,'B', 'C', 'D']

error = [0.23722952107696088, 0.25505883348061764, 0.26038015798295744, 0.26073839861422]
pvalue = [0.000076, 0.000025, 0.813956, 0.012581]

fig, ax = plt.subplots()
ax.bar(x_labels, X, width=0.4, align='center', yerr=error)
plt.show()
MaxPowers
  • 5,235
  • 2
  • 44
  • 69
jaime
  • 15
  • 1
  • 5
  • I don't really know what you call easy way, from [this](https://stackoverflow.com/questions/14270391/python-matplotlib-multiple-bars) you can make appears a second column aside which represent the Pvalue. That is not impressive but it is a way to represent the different significance between the "groups" in `x_labels`. – AvyWam Feb 26 '19 at 17:50
  • 1
    There are several helpful possible answers in [this question](https://stackoverflow.com/questions/30228069/how-to-display-the-value-of-the-bar-on-each-bar-with-pyplot-barh) – G. Anderson Feb 26 '19 at 17:58

2 Answers2

1

It can be done like the way shown here with slight modification

import matplotlib.pyplot as plt   
X= [-0.9384815619939103, 1.0755888058123153, 0.061274066731665564,0.65064830688728]
x_labels = ['A' ,'B', 'C', 'D']
error = [0.23722952107696088, 0.25505883348061764, 0.26038015798295744, 0.26073839861422]
pvalue = [0.000076, 0.000025, 0.813956, 0.012581]

fig, ax = plt.subplots()
rects = ax.bar(x_labels, X, width=0.4, align = 'center', yerr=error)



def autolabel(rects,  pvalue, xpos='center',):
    """
    Attach a text label above each bar in *rects*, displaying its height.

    *xpos* indicates which side to place the text w.r.t. the center of
    the bar. It can be one of the following {'center', 'right', 'left'}.
    """

    xpos = xpos.lower()  # normalize the case of the parameter
    ha = {'center': 'center', 'right': 'left', 'left': 'right'}
    offset = {'center': 0.5, 'right': 0.57, 'left': 0.43}  # x_txt = x + w*off

    for i, rect in enumerate(rects):
        height = rect.get_height()
        ax.text(rect.get_x() + rect.get_width()*offset[xpos], 1.01*height,
                'p = {}'.format(pvalue[i]), ha=ha[xpos], va='bottom')
autolabel(rects, pvalue, "left")

plt.show()

which results in enter image description here

plasmon360
  • 4,109
  • 1
  • 16
  • 19
  • 1
    Beat me to it; +1! I was following the same answer, but I found it looked a little clearer with `ax.text(rect.get_x(),1.2,"P-value:\n{}".format(pval))`. But again that's just aesthetic choice – G. Anderson Feb 26 '19 at 18:06
  • @jaime If this answer was helpful. Please accept it. – plasmon360 Feb 26 '19 at 21:36
1

Here is another solution which puts the p-values to the plot's legend. For my eyes, this is more pleasant compared to plotting the p-values over the bars.

import matplotlib.pyplot as plt

X= [-0.9384815619939103, 1.0755888058123153, 0.061274066731665564, 0.65064830688728]
x_labels = ['A' ,'B', 'C', 'D']

error = [0.23722952107696088, 0.25505883348061764, 0.26038015798295744, 0.26073839861422]
pvalue = [0.000076, 0.000025, 0.813956, 0.012581]

fig, ax = plt.subplots()
cont = ax.bar(x_labels, X, width=0.4, align='center', yerr=error)

for i, art in enumerate(cont):
    art.set_color('C{}'.format(i))

ax.legend(cont.patches, [r'$p={:.6f}$'.format(pv) for pv in pvalue])

Bar plot with p-values in legend.

MaxPowers
  • 5,235
  • 2
  • 44
  • 69
  • +1 for a creative solution, but it may rely too much on color vision for many applications. Maybe a horizontal legend atop the plot? – G. Anderson Feb 26 '19 at 21:39