为什么在显示或保存图形时裁剪图片注释? [英] Why is picture annotation cropped when displaying or saving figure?

查看:40
本文介绍了为什么在显示或保存图形时裁剪图片注释?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直致力于制作一些箱线图,其中包含一张显示箱线图各部分代表什么的图像.如右上方所示.很好.

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

I have been working at producing some boxplots that include an image that shows what the parts of boxplots represent. As shown in the top right here. This is fine.

But, if I remove the green dashed line, which removes the legend, then the little boxplot image is cropped out when I view the plot in jupyter, but also if I save it as image file.e.g.

The solution offered here using 'tight' doesn't work, i.e.:

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

Nor does:

plt.tight_layout()

I've also tried using AnnotationBbox but can't find a solution.

Working example code below:

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') 

解决方案

Using guidance from @ImportanceOfBeingErnest I have got what I required but in saved plots only, the jupyter inline displays are still cropped (not showing annotation box) using the code below:

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]])

I found that I had to delete the 'bbox_inches='tight' part from the final save statement or I found that my 'N=...' text annotations were being cropped. Can't believe it is this hard to do!

gives:

这篇关于为什么在显示或保存图形时裁剪图片注释?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆