Search code examples
pythonpython-3.xmatplotlibplot

Creating a contour-enhanced funnel plot


I want to create a Contour-Enhanced funnel plot (not a funnel chart),to test the small-study effect in meta-analysis like the following:

![R funnelplot

The above plot was created in R, which has several packages for doing this. However, I want to create it in Python, using matplotlib and pandas. How can I do this? I have tried Pythonmeta package and got this funnel plot enter image description here

This is the source code of the package:

    def __init__(self,size=[6,6],dpi=80): #set figure
        self.size=size #inchs
        self.dpi=dpi   #default:80pts
        self.title="Meta-analysis Results "  
        self.nototal=False
        plt.rcParams['font.sans-serif']=['SimHei'] 
        plt.rcParams['axes.unicode_minus']=False
        logger.info("Load Fig().")
    def funnel (self,effs):
        myfig = Fig_Funnel (self.size,self.dpi,effs)
        return myfig```
    def Fig_Funnel (size,dpi,effs):
        myfig = plt.figure(linewidth=1,figsize=size,dpi=dpi)
        myfig.set_size_inches(size)
        x=[];y=[]
        for i in range(1,len(effs)):
            x.append(effs[i][1])
            y.append(effs[i][6])
        lbl,=plt.plot(x,y,"o", lw=1)

    
        ymax=max(y)+0.2
        plt.ylim(ymax,0)
        plt.plot([effs[0][1],effs[0][1]],[0,ymax],color="blue", linestyle="--",
        lw=1)
        plt.plot([effs[0][1],effs[0][1]-1.96*ymax],[0,ymax],color="blue",
        linestyle="--", lw=1)
        plt.plot([effs[0][1],effs[0][1]+1.96*ymax],[0,ymax],color="blue",
        linestyle="--", lw=1)
        ax = gca()
        ax.spines['right'].set_color('none')
        ax.spines['top'].set_color('none')
        ax.xaxis.set_ticks_position('bottom')
        ax.yaxis.set_ticks_position('left')

        plt.xlabel("Effect Size")
        plt.ylabel("Standard Error")
        myfig.tight_layout() 
        return myfig

Solution

  • Finally, I created it myself.:)

    First of all, to understand the concept of a Contour-enhanced funnel plot, I recommend reading Jaime L Peters paper.

    To create the plot, I used the following code

    def CEfunnelplot(rults):      #to draw contour enhanced funnel plot
    
    fig=plt.figure(figsize=(9,8))
    ax=gca()
    x=logES(rults)
    y=SE(rults)      
    
    plt.xlim(min(x)-5,max(x)+2)  #the xlim can change manually
    plt.ylim(max(y)+0.1,0)
    ax.set_facecolor(color="whitesmoke")
    tes=(rults[0][1])
    logtes=math.log(rults[0][1])
    
    
    plt.plot ([0,(-2.58*max(y))],[0,max(y)], linestyle="None", lw=1)
    plt.plot ([0,(2.58*max(y))],[0,max(y)], linestyle="None", lw=1)
    
    trianglex = [ -2.58*max(y), 0, 2.58*max(y)] 
    triangley = [ max(y),0, max(y)] 
    for i in range(3):
        plt.plot(trianglex, triangley,color="lightgray")
    plt.fill(trianglex, triangley,"lightgray")
    
    plt.plot ([0,(-1.96*max(y))],[0,max(y)], linestyle="None", lw=1)
    plt.plot ([0,(1.96*max(y))],[0,max(y)], linestyle="None", lw=1)
    
    trianglex = [ -1.96*max(y), 0,1.96*max(y)] 
    triangley = [ max(y),0, max(y)] 
    for i in range(3):
        plt.plot(trianglex, triangley,color="darkgrey")
    plt.fill(trianglex, triangley,"darkgrey")
    
    
    plt.plot ([0,(-1.65*max(y))],[0,max(y)], linestyle="None", lw=1)
    plt.plot ([0,(1.65*max(y))],[0,max(y)], linestyle="None", lw=1)
    
    trianglex = [ -1.65*max(y), 0,1.65*max(y)] 
    triangley = [ max(y),0, max(y)] 
    for i in range(3):
        plt.plot(trianglex, triangley,color="white")
    plt.fill(trianglex, triangley,"white")
    
    plt.plot ([logtes,logtes],[0,max(y)],color="blue", linestyle="--", lw=1)
    plt.plot ([logtes,logtes-1.96*max(y)],[0,max(y)],color="blue", linestyle="--", lw=1)
    plt.plot ([logtes,logtes+1.96*max(y)],[0,max(y)],color="blue", linestyle="--", lw=1)
    plt.plot(x,y,"o",lw=1,color="k")
    
    ax = gca()
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    colors = ['whitesmoke', 'lightgray', 'darkgrey',"white"]
    lines =[Line2D([0], [0], color=c, linewidth=3, linestyle='solid') for c in colors]
    labels = ["p < 1%","1%< p <5%","5%< p <10%","p > 10%"]
    plt.legend(lines, labels,shadow=True)    
    
    plt.xlabel("logRR",fontsize=14 )
    plt.ylabel("Standard Error",fontsize=14,rotation=90 )
    plt.savefig("Contour Enhanced Funnel plot.jpg")
    

    I used This sample code for creating the legend and This code to color the plot. The result is as below:

    Contour-Enhanced funnel plot

    If you like to change the marker of legend to "square", you can change the code as below

    lines =[Line2D([0], [0],color=c,linewidth=3,linestyle='None',marker="s") for c in colors]
    

    Figure with square markers for legend