为什么在显示或保存图形时裁剪图片注释?

时间:2019-05-29 12:53:49

标签: python pandas matplotlib seaborn

我一直在制作一些箱形图,其中包括一张显示箱形图各部分代表什么的图像。如右上方所示。很好。

with legend

但是,如果我删除绿色虚线也删除了图例,那么当我在jupyter中查看该图时,也会裁剪出小盒子图图像,而且如果将其另存为图像文件也是如此。 enter image description here

here使用“紧密”提供的解决方案不起作用,即:

plt.savefig("test1.jpg", dpi=300,bbox_inches='tight')

也没有:

plt.tight_layout()

我也尝试使用AnnotationBbox,但是找不到解决方案。

下面的工作示例代码:

import numpy as np

import pandas as pd
import seaborn as sns
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.offsetbox import (TextArea, DrawingArea, OffsetImage,
                                  AnnotationBbox)
df = pd.DataFrame(np.random.randn(40, 4), columns=list('ABCD'))
df['Class']=list('ADFADAFDADFAFDAADFAFDAFDDFADFAFDADDFDFAD')


assay=df

factor_to_plot='A'
f=factor_to_plot

x_axis_factor='Class'
g=x_axis_factor

pcntls=assay.groupby([g]).describe(percentiles=[0.05,0.1,0.25,0.5,0.75,0.9,0.95])
sumry= pcntls[f].T
#print sumry
ordered=sorted(assay[g].dropna().unique())

#set figure size and scale text
plt.rcParams['figure.figsize']=(15,10)
plt.rcParams['figure.dpi'] = 300
text_scaling=1.9
sns.set(style="whitegrid")
sns.set_context("paper", font_scale=text_scaling) 

#plot boxplot
ax=sns.boxplot(x=assay[g],y=assay[f],width=0.5,order=ordered, whis=[10,90],data=assay, showfliers=False,color='lightblue', 
            showmeans=True,meanprops={"marker":"x","markersize":12,"markerfacecolor":"white", "markeredgecolor":"black"})


#add dashed line at a value
plt.axhline(0.3, color='green',linestyle='dashed', label="S%=0.3")

#this line sets the scale to logarithmic
#ax.set_yscale('log')

#add legend for dashed line
#plt.legend(markerscale=1.5,loc='center left',bbox_to_anchor=(1.0, 0.5))

#plt.title("Assay data")

#add gridlines (use for log plots)
plt.grid(True, which='both')


#plot additional percentiles not included in boxplots
ax.scatter(x=sorted(list(sumry.columns.values)),y=sumry.loc['5%'],s=120,color='white',edgecolor='black') 
ax.scatter(x=sorted(list(sumry.columns.values)),y=sumry.loc['95%'],s=120,color='white',edgecolor='black')




#next line is important, select a column that has no blanks or nans as the total items are counted to produce
#N= annotations to plot. 
assay['value']=assay['B']

vals=assay.groupby([g])['value'].count()
j=vals

ymin, ymax = ax.get_ylim()
xmin, xmax = ax.get_xlim()
#print ymax

#put n= values at top of plot    
x=0
for i in range(len(j)):

    plt.text(x = x , y = ymax, s = "N=\n" +str(int(j[i])),horizontalalignment='center')
    #plt.text(x = x , y = 102.75, s = "n=",horizontalalignment='center')
    x+=1


#add legend image
img = plt.imread("legend4.jpg")
plt.figimage(img, 3900,1800, zorder=1, alpha=1)

'''xy = [1.1, 0.8]
fn = "legend4.jpg"
arr_img = plt.imread(fn, format='jpg')

imagebox = OffsetImage(arr_img, zoom=0.2)
imagebox.image.axes = ax

ab = AnnotationBbox(imagebox, xy,
                        boxcoords="figure fraction",


                        )

ax.add_artist(ab)'''



#plt.tight_layout()

#use the section below to adjust the y axis lable format to avoid default of 10^1 etc for log scale plots.
#ylabels = ['{:.1f}'.format(y) for y in ax.get_yticks()]
#ax.set_yticklabels(ylabels)

plt.savefig("test1.jpg", dpi=300,bbox_inches='tight') 

1 个答案:

答案 0 :(得分:0)

使用@ImportanceOfBeingErnest的指南,我已经得到了所需的信息,但是仅在保存的绘图中,使用以下代码仍然裁剪了 jupyter内联显示(未显示注释框):

import numpy as np

import pandas as pd
import seaborn as sns
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.offsetbox import (TextArea, DrawingArea, OffsetImage,
                                  AnnotationBbox)
df = pd.DataFrame(np.random.randn(40, 4), columns=list('ABCD'))
df['Class']=list('ADFADAFDADFAFDAADFAFDAFDDFADFAFDADDFDFAD')


assay=df

factor_to_plot='A'
f=factor_to_plot

x_axis_factor='Class'
g=x_axis_factor

pcntls=assay.groupby([g]).describe(percentiles=[0.05,0.1,0.25,0.5,0.75,0.9,0.95])
sumry= pcntls[f].T
#print sumry
ordered=sorted(assay[g].dropna().unique())

#set figure size and scale text
plt.rcParams['figure.figsize']=(15,10)
plt.rcParams['figure.dpi'] = 300
text_scaling=1.9
sns.set(style="whitegrid")
sns.set_context("paper", font_scale=text_scaling) 

#plot boxplot
ax=sns.boxplot(x=assay[g],y=assay[f],width=0.5,order=ordered, whis=[10,90],data=assay, showfliers=False,color='lightblue', 
            showmeans=True,meanprops={"marker":"x","markersize":12,"markerfacecolor":"white", "markeredgecolor":"black"})


#add dashed line at a value
#plt.axhline(0.3, color='green',linestyle='dashed', label="S%=0.3")

#this line sets the scale to logarithmic
#ax.set_yscale('log')

#add legend for dashed line
#plt.legend(markerscale=1.5,loc='center left',bbox_to_anchor=(1.0, 0.5))

#plt.title("Assay data")

#add gridlines (use for log plots)
plt.grid(True, which='both')


#plot additional percentiles not included in boxplots
ax.scatter(x=sorted(list(sumry.columns.values)),y=sumry.loc['5%'],s=120,color='white',edgecolor='black') 
ax.scatter(x=sorted(list(sumry.columns.values)),y=sumry.loc['95%'],s=120,color='white',edgecolor='black')




#next line is important, select a column that has no blanks or nans as the total items are counted to produce
#N= annotations to plot. 
assay['value']=assay['B']

vals=assay.groupby([g])['value'].count()
j=vals

ymin, ymax = ax.get_ylim()
xmin, xmax = ax.get_xlim()
#print ymax

#put n= values at top of plot    
x=0
for i in range(len(j)):

    plt.text(x = x , y = ymax, s = "N=\n" +str(int(j[i])),horizontalalignment='center')

    x+=1


#add legend image

fn = plt.imread("legend4.jpg")
arr_img = fn

imagebox = OffsetImage(arr_img, zoom=0.2)
imagebox.image.axes = ax

ab = AnnotationBbox(imagebox, xy=(1.05, 0.5), xycoords="axes fraction",
                                        boxcoords="offset points",
                    pad=0.5

                    )

ax.add_artist(ab)

plt.savefig('test.png', bbox_extra_artists=[a.offsetbox for a in [ab]])

我发现我不得不从最终的保存语句中删除'bbox_inches ='tight'部分,或者发现我的'N = ...'文本注释已被裁剪。不敢相信这很难做到!

给予:

plot with image key