Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
312 views
in Technique[技术] by (71.8m points)

python - footnote/annotate overlapping with xlabel

My code: Please scroll down to ##### Part where the question is related #####

This is part of the repository: https://github.com/soobinck/rotarod_ML/featureImportance/featureImportance_decisionTreeImportancePlot.py

import os
import string

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from utils.getDirAbsPath import outputAbsPath

inputCSV = './output.csv'

# Plot importance when the number of intervals is 2.

interval = len(string.ascii_lowercase)
df = pd.read_csv(inputCSV, index_col=0)
df01 = df[['0', '1']]

bins = np.array_split(df01, len(df01) / interval)[1]
df01 = pd.DataFrame(bins)

xlabel = '(i)th interval'
ylabel = 'feature importance'
title = 'Feature importance in classifying genotypes (%i iterations)' % interval
outputPath = os.path.join(outputAbsPath(), 'featureImportance', 'accuracies.png')
footnote = footnote = 'Classified with mean step up height as the model's input. Classified with mean step up height as the model's input. Classified with mean step up height as the model's input. Classified with mean step up height as the model's input. Classified with mean step up height as the model's input. '


# Plotting

fig, ax = plt.subplots(figsize=(15, 11), tight_layout=True)
plt.subplots_adjust(hspace=1.0, wspace=0.02, bottom=0.17)

# Creating axes instance
bp = ax.boxplot(df, patch_artist=True,
                notch='True')

# changing color and linewidth of
# whiskers
for whisker in bp['whiskers']:
    whisker.set(color='#8B008B',
                linestyle=":")
# changing color and linewidth of
# caps
for cap in bp['caps']:
    cap.set(color='#8B008B')

# changing color and linewidth of
# medians
for median in bp['medians']:
    median.set(color='red')

# changing style of fliers
for flier in bp['fliers']:
    flier.set(marker='D',
              color='#e7298a',
              alpha=0.5)

# x-axis labels
ax.set_xlabel(xlabel)
ax.set_ylabel(ylabel)
# Adding title
plt.title(title)
fig.subplots_adjust(bottom=0.2)


##### Part where the question is related #####
ft = plt.figtext(0, 0, footnote, wrap=True, va='bottom', fontsize=11)

#Have tried:
# ax.annotate(footnote, (0,-0.2), xycoords='figure fraction')
# plt.subplots_adjust(hspace=1.0, wspace=0.02, bottom=0.17)
# fig.subplots_adjust(bottom=0.2)



plt.tight_layout()

##### Part where the question is related #####

fig.savefig(outputPath)
# pickle.dump(fig, open((outputPath + '.fig.pickle'), 'wb'))

# show plot
fig.show()
print('%s saved.' % outputPath)

This yields plot

I keep having the footnote covered by the xlabel. I tried pretty much all of the solutions possible I could found on the net. Can someone please let me know how to add long footnotes to a graph? The format has to be like in the paper. Left and right aligned with the graph's edges (not the figure size). Left aligned but spanned so that lines except for the last line spanned to fill the entire line.

Example here: Example

Thank you so much in advance! :)

question from:https://stackoverflow.com/questions/65940496/footnote-annotate-overlapping-with-xlabel

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Using this excellent gist with a minor fix for the width calculation and manually setting the bottom pad (you can get the correct value using an interactive plot backend where you can adjust the boders) we get:

import matplotlib.pyplot as plt
import matplotlib as mpl

fig,ax = plt.subplots()
ax.plot([1,2])
ax.set_xlabel('x-label')
fig.subplots_adjust(bottom=0.275)

footnote = 'Classified with mean step up height as the model's input. Classified with mean step up height as the model's input. Classified with mean step up height as the model's input. Classified with mean step up height as the model's input. Classified with mean step up height as the model's input. '

#https://gist.github.com/dneuman/90af7551c258733954e3b1d1c17698fe
class WrapText(mpl.text.Text):
    """
    WrapText(x, y, s, width, widthcoords, **kwargs)
    x, y       : position (default transData)
    text       : string
    width      : box width
    widthcoords: coordinate system (default screen pixels)
    **kwargs   : sent to matplotlib.text.Text
    Return     : matplotlib.text.Text artist
    """
    def __init__(self,
                 x=0, y=0, text='',
                 width=0,
                 widthcoords=None,
                 **kwargs):
        mpl.text.Text.__init__(self,
                 x=x, y=y, text=text,
                 wrap=True,
                 clip_on=False,
                 **kwargs)
        if not widthcoords:
            self.width = width
        else:
            a = widthcoords.transform_point([(0,0),(width,0)])
            self.width = a[1][0]-a[0][0]

    def _get_wrap_line_width(self):
        return self.width

trans = mpl.transforms.blended_transform_factory(
    ax.transAxes, fig.transFigure)    
wtxt = WrapText(0, 0, footnote, width=1, va='bottom', 
                widthcoords=ax.transAxes, transform=trans)
ax.add_artist(wtxt)
plt.show()

enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...