如何在matplotlib中绘制的森林图中绘制水平线?

2024-09-29 19:30:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在用一个软件包画一块林地。森林地块的源代码如下:

def Fig_Forest (size,dpi,es_w_ci, titletxt="Meta-analysis Results",no_ttl=False):
    if es_w_ci[0][0] in "OR,RR" :
        def _x_tran0(x):
            return math.log(x)
        def _x_tran1(x):
            return math.exp(x)
    elif es_w_ci[0][0] in "RD,MD,SMD" :
        def _x_tran0(x):
            return x
        def _x_tran1(x):
            return x
    else:
        Err="error.(failed to get effect size while drawing forest plot)"
        raise Exception(Err)

    myfig = plt.figure(linewidth=1, figsize=size, dpi=dpi)  #Frameon=False, num="Forest plot by PythonMeta", 
    myfig.set_size_inches(size)
    plt.title(titletxt)
    ax = gca()
    ax.spines['right'].set_color('none')
    ax.spines['left'].set_color('none')
    ax.xaxis.set_ticks_position('bottom')
    ax.yaxis.set_ticks_position('left')
    plt.xticks(fontsize=9)
    plt.yticks(fontsize=9)
    xlim=[];y_k=0;subgrp=[]  
    for i in range(len(es_w_ci)):
        xlim.append(es_w_ci[i][3])
        xlim.append(es_w_ci[i][4])
        stdname=es_w_ci[i][0]
        if stdname[0:5]=="<sub>":  #this line is a subgroup
            subgrp.append(es_w_ci[i])

    xmin= _x_tran0(min(xlim))
    xmax= _x_tran0(max(xlim))
    xmax=max(abs(xmin),abs(xmax))
    xmin=-xmax                    
    plt.xlim(xmin*1.1,xmax*1.1)
    ylabel=[i[0].replace("<sub>","") for i in es_w_ci[1:]]
    if no_ttl==True :
        ax.set_yticks(range(len(es_w_ci)))
        ymax=len(es_w_ci)
        ylabel.extend([""])
        y_k=0
    else:
        ax.set_yticks(range(len(es_w_ci)+3))
        ymax=len(es_w_ci)+3
        ylabel.extend(["","Overall","",""])
        y_k=3
    plt.ylim(0, ymax)
    ylabel.reverse()
    ax.set_yticklabels(ylabel)
    xt([round(_x_tran1(x),2) for x in ax.get_xticks()])
    plt.plot([0,0], [0,len(es_w_ci)+3], 'black')     

    if len(subgrp)>0:
        weight_all=subgrp[0][2]
    else:
        weight_all=es_w_ci[0][2]
    N=es_w_ci[0][5];k=0;i_subgrp=0
    for i in range(1,len(es_w_ci)):
        stdname=es_w_ci[i][0]
        if stdname[0:5]=="<sub>":  #this line is a subgroup
            i_subgrp+=1
            if i_subgrp>len(subgrp)-1:
                i_subgrp=len(subgrp)-1
            weight_all=subgrp[i_subgrp][2]
            x=[_x_tran0(es_w_ci[i][1]),
               _x_tran0(es_w_ci[i][3]),
               _x_tran0(es_w_ci[i][1]),
               _x_tran0(es_w_ci[i][4]),
               _x_tran0(es_w_ci[i][1])]
            y=[len(es_w_ci)-i+y_k+0.2,
               len(es_w_ci)-i+y_k,
               len(es_w_ci)-i+y_k-0.2,
               len(es_w_ci)-i+y_k,
               len(es_w_ci)-i+y_k+0.2]
            if (es_w_ci[i][9]<50) :
                plt.fill(x,y,color="blue", lw=1)  #filled: I2<50
            else :
                plt.plot(x,y, 'blue', lw=1)       #empty: I2>50

            continue

        #weight
        weight=es_w_ci[i][2]/weight_all

        #shadow X line
        lncolor,lnstyle=("blue","-")
        plt.plot([_x_tran0(es_w_ci[i][3]),_x_tran0(es_w_ci[i][4])], [len(es_w_ci)-i+y_k,len(es_w_ci)-i+y_k], lncolor, linestyle=lnstyle, lw=1)
        #central block
        k=weight*0.2+0.05 
        x=[_x_tran0(es_w_ci[i][1])-k*(xmax*2.2/ymax),
           _x_tran0(es_w_ci[i][1])+k*(xmax*2.2/ymax),
           _x_tran0(es_w_ci[i][1])+k*(xmax*2.2/ymax),
           _x_tran0(es_w_ci[i][1])-k*(xmax*2.2/ymax),
           _x_tran0(es_w_ci[i][1])-k*(xmax*2.2/ymax)]
        y=[len(es_w_ci)-i+y_k+k,
           len(es_w_ci)-i+y_k+k,
           len(es_w_ci)-i+y_k-k,
           len(es_w_ci)-i+y_k-k,
           len(es_w_ci)-i+y_k+k]
        plt.fill(x,y,color=lncolor, lw=1)  #filled: 

    if no_ttl==True:
        pass
    else:
        #draw total ES from es_w_ci[0]
        x=[_x_tran0(es_w_ci[0][1]),
           _x_tran0(es_w_ci[0][3]),
           _x_tran0(es_w_ci[0][1]),
           _x_tran0(es_w_ci[0][4]),
           _x_tran0(es_w_ci[0][1])]
        y=[2.3,2,1.7,2,2.3]
        if (es_w_ci[0][9]<50) :
            plt.fill(x,y,color="black", lw=1)  #filled: I2<50 
        else :
            plt.plot(x,y, 'black', lw=1)       #empty: I2>50 

    plt.xlabel("Favours Experiment  Favours Control       ",fontsize=10) #effect direction,see Cochrane rules
    #plt.ylabel("Studies")
    myfig.tight_layout() 
    return myfig

导入包后,我向forest plot添加了一些函数,以提供我想要的图,如下所示:

    plt.yticks(fontsize=8,ha="left",weight="bold")
    
    plt.text(-0.6,0, totallabel,fontsize=8, style='oblique', ha="right",
         va='bottom', 
   multialignment="left",wrap=True,linespacing=1.2,weight="bold")
    
    plt.text(5.8,2.9, s,fontsize=8, style='normal', ha="left",
         va='bottom', multialignment="left",linespacing=2.21,weight="bold")
   
    plt.text(4.8,0.8, ss,fontsize=8, style='normal', ha="center",
         va='bottom', multialignment="left",linespacing=2.45,weight="bold")
   
    plt.xlabel(" Favours Placebo         Favours Haloperidol       ",fontsize=10)
    plt.tight_layout()
    ax=plt.gca()
    plt.hlines(1, 0.85,5.10, colors='g', linestyles='solid')

结果是:
The forestplot

正如您所看到的,水平线没有绘制最小、最大范围限制。 我对Python很陌生,你能告诉我如何解决它吗? 我使用了axhline,plt.plot并转换了协调器,但没有任何变化


Tags: cilenifesplotpltaxleft

热门问题