Python 表示条形图中的统计显著差异

Python 表示条形图中的统计显著差异,python,matplotlib,figure,Python,Matplotlib,Figure,我使用条形图来表示每组的数据。这些条中的一些条彼此之间存在显著差异。如何显示条形图中的显著差异 import numpy as np import matplotlib.pyplot as plt menMeans = (5, 15, 30, 40) menStd = (2, 3, 4, 5) ind = np.arange(4) # the x locations for the groups width=0.35 p1 = plt.bar(ind, menMeans, wi

我使用条形图来表示每组的数据。这些条中的一些条彼此之间存在显著差异。如何显示条形图中的显著差异

import numpy as np
import matplotlib.pyplot as plt
menMeans   = (5, 15, 30, 40)
menStd     = (2, 3, 4, 5)
ind = np.arange(4)    # the x locations for the groups
width=0.35
p1 = plt.bar(ind, menMeans, width=width, color='r', yerr=menStd)
plt.xticks(ind+width/2., ('A', 'B', 'C', 'D') )
我的目标是


我在这里做了几件事,建议在处理复杂绘图时使用。将自定义格式提取到一个字典中,当您想要更改参数时,它使操作变得简单-并且您可以将此字典传递给多个绘图。我还编写了一个自定义函数来注释itervalues,如果您真的愿意,它还可以在
(a,C)
之间进行注释(我坚持我的意见,这不是正确的可视化方法)。一旦数据发生变化,它可能需要一些调整,但这应该会让你走上正确的轨道

import numpy as np
import matplotlib.pyplot as plt
menMeans   = (5, 15, 30, 40)
menStd     = (2, 3, 4, 5)
ind  = np.arange(4)    # the x locations for the groups
width= 0.7
labels = ('A', 'B', 'C', 'D')

# Pull the formatting out here
bar_kwargs = {'width':width,'color':'y','linewidth':2,'zorder':5}
err_kwargs = {'zorder':0,'fmt':None,'linewidth':2,'ecolor':'k'}  #for matplotlib >= v1.4 use 'fmt':'none' instead

fig, ax = plt.subplots()
ax.p1 = plt.bar(ind, menMeans, **bar_kwargs)
ax.errs = plt.errorbar(ind, menMeans, yerr=menStd, **err_kwargs)


# Custom function to draw the diff bars

def label_diff(i,j,text,X,Y):
    x = (X[i]+X[j])/2
    y = 1.1*max(Y[i], Y[j])
    dx = abs(X[i]-X[j])

    props = {'connectionstyle':'bar','arrowstyle':'-',\
                 'shrinkA':20,'shrinkB':20,'linewidth':2}
    ax.annotate(text, xy=(X[i],y+7), zorder=10)
    ax.annotate('', xy=(X[i],y), xytext=(X[j],y), arrowprops=props)

# Call the function
label_diff(0,1,'p=0.0370',ind,menMeans)
label_diff(1,2,'p<0.0001',ind,menMeans)
label_diff(2,3,'p=0.0025',ind,menMeans)


plt.ylim(ymax=60)
plt.xticks(ind, labels, color='k')
plt.show()
将numpy导入为np
将matplotlib.pyplot作为plt导入
menMeans=(5,15,30,40)
menStd=(2,3,4,5)
ind=np.arange(4)#组的x个位置
宽度=0.7
标签=('A','B','C','D')
#从这里拉出格式
bar_kwargs={'width':width,'color':'y','linewidth':2,'zorder':5}
err_kwargs={'zorder':0,'fmt':None,'linewidth':2,'ecolor':'k'}35;对于matplotlib>=v1.4,请改用'fmt':'None'
图,ax=plt.子批次()
ax.p1=plt.bar(ind,menMeans,**bar_-kwargs)
ax.errs=plt.errorbar(ind,menMeans,yerr=menStd,**err_-kwargs)
#用于绘制差异条的自定义函数
def标签_diff(i,j,text,X,Y):
x=(x[i]+x[j])/2
y=1.1*最大值(y[i],y[j])
dx=abs(X[i]-X[j])
道具={'connectionstyle':'bar','arrowstyle':'-'\
“收缩A”:20,“收缩B”:20,“线宽”:2}
注释(文本,xy=(X[i],y+7),zorder=10)
ax.注释(“”,xy=(X[i],y),xytext=(X[j],y),arrowprops=props)
#调用函数
标签差异(0,1,'p=0.0370',ind,menMeans)

label_diff(1,2,'p上述答案启发我自己编写了一个小而灵活的函数:

def barplot_annotate_brackets(num1, num2, data, center, height, yerr=None, dh=.05, barh=.05, fs=None, maxasterix=None):
    """ 
    Annotate barplot with p-values.

    :param num1: number of left bar to put bracket over
    :param num2: number of right bar to put bracket over
    :param data: string to write or number for generating asterixes
    :param center: centers of all bars (like plt.bar() input)
    :param height: heights of all bars (like plt.bar() input)
    :param yerr: yerrs of all bars (like plt.bar() input)
    :param dh: height offset over bar / bar + yerr in axes coordinates (0 to 1)
    :param barh: bar height in axes coordinates (0 to 1)
    :param fs: font size
    :param maxasterix: maximum number of asterixes to write (for very small p-values)
    """

    if type(data) is str:
        text = data
    else:
        # * is p < 0.05
        # ** is p < 0.005
        # *** is p < 0.0005
        # etc.
        text = ''
        p = .05

        while data < p:
            text += '*'
            p /= 10.

            if maxasterix and len(text) == maxasterix:
                break

        if len(text) == 0:
            text = 'n. s.'

    lx, ly = center[num1], height[num1]
    rx, ry = center[num2], height[num2]

    if yerr:
        ly += yerr[num1]
        ry += yerr[num2]

    ax_y0, ax_y1 = plt.gca().get_ylim()
    dh *= (ax_y1 - ax_y0)
    barh *= (ax_y1 - ax_y0)

    y = max(ly, ry) + dh

    barx = [lx, lx, rx, rx]
    bary = [y, y+barh, y+barh, y]
    mid = ((lx+rx)/2, y+barh)

    plt.plot(barx, bary, c='black')

    kwargs = dict(ha='center', va='bottom')
    if fs is not None:
        kwargs['fontsize'] = fs

    plt.text(*mid, text, **kwargs)
def条形图注释括号(num1、num2、数据、中心、高度、YER=None、dh=0.05、barh=0.05、fs=None、maxasterix=None):
""" 
用p值注释条形图。
:param num1:要将支架置于其上的左杆的数量
:param num2:用于放置支架的右侧杆的数量
:param data:要写入的字符串或用于生成星号的数字
:param center:所有条的中心(如plt.bar()输入)
:param height:所有条的高度(如plt.bar()输入)
:param yerr:所有条的yerrs(如plt.bar()输入)
:param dh:轴坐标(0到1)中杆/杆+yerr上的高度偏移
:param barh:轴坐标中的条形高度(0到1)
:param fs:font size
:param maxasterix:要写入的最大星号数(对于非常小的p值)
"""
如果类型(数据)为str:
文本=数据
其他:
#*p<0.05
#**为p<0.005
#***为p<0.0005
#等等。
文本=“”
p=0.05
而数据
这使我可以得到一些相对简单的注释,例如:

heights = [1.8, 2, 3]
bars = np.arange(len(heights))

plt.figure()
plt.bar(bars, heights, align='center')
plt.ylim(0, 5)
barplot_annotate_brackets(0, 1, .1, bars, heights)
barplot_annotate_brackets(1, 2, .001, bars, heights)
barplot_annotate_brackets(0, 2, 'p < 0.0075', bars, heights, dh=.2)
heights=[1.8,2,3]
钢筋=np.arange(长度(高度))
plt.图()
水平杆(杆、高度、对齐和居中)
plt.ylim(0,5)
条形图注释括号(0,1,1,条形图,高度)
条形图注释括号(1,2,001,条形图,高度)
条形图注释括号(0,2,'p<0.0075',条形图,高度,dh=.2)

如果使用matplotlib并查找箱线图注释,请使用我的代码作为函数:

统计注释 其中“x1”和“x2”是要比较的两列,“ARRAY”是用于说明箱线图的列表列表。“TXT”是字符串格式的文本,如p值或有效/无效

因此,请用以下词语来称呼它:

AnnoMe(1, 2, MyArray, "p-value=0.02")

唯一要在本地进行的比较是相邻的吗?也就是说,您是否只想显示
(A,B)(B,C)(C,D)
,而不是
(A,C)之间的差异
?不,我想在所有可能的对之间进行比较。这可能很难在图表上显示出来,尤其是在项目很多的情况下。如果您有N=10个项目,则有45个不同的成对比较!看起来您可以在矩阵上显示成对的p值。这样行吗?您只是想实现所附的绘图,或者您真的想要@Hooked建议的矩阵吗?大多数情况下,您不需要比较所有可能的对。在上述情况下,比较(a,C)或(a,D)或(B,D)不会提供任何新信息。因此,理想情况下,我想比较所选对,比如在一种情况下,它可以是(a,B),(B,C)和(C,D)(如上所述)如果可以是(A,B),(A,C)和(A,D)。非常感谢。非常有用。我只是将
ax.annotate(text,xy=(X[I],y+7),zorder=10)
更改为
ax.annotate(text,xy=(X,y+7),zorder=10)
使p值居中。@imsc这是我最初使用的,但这是文本块左侧的位置,而不是文本块的中心。对我来说,这似乎与该位置有点偏离中心。不管怎样,我希望你看到如何调整!哦,是的,我还将
ha='center'
放在
annota中te
AnnoMe(1, 2, MyArray, "p-value=0.02")