Insert matplotlib images into a pandas dataframe

前端 未结 1 568
刺人心
刺人心 2020-12-06 07:56

PURPOSE: I am currently working with rdkit to colour the structures of my molecules according to rdkit.Chem.Draw.SimilarityMaps. Now, I would l

相关标签:
1条回答
  • 2020-12-06 08:40

    What you see as Figure (200x200) is the __repr__ string of the matplotlib Figure class. It is the text representation of that python object (the same that you would see when doing print(fig)).

    What you want instead is to have an actual image in the table. An easy option would be to save the matplotlib figure as png image, create an html tag, <img src="some.png" /> and hence show the table.

    import pandas as pd
    import numpy as np;np.random.seed(1)
    import matplotlib.pyplot as plt
    import matplotlib.colors
    
    df = pd.DataFrame({"info" : np.random.randint(0,10,10), 
                       "status" : np.random.randint(0,3,10)})
    
    cmap = matplotlib.colors.ListedColormap(["crimson","orange","limegreen"])
    
    def createFigure(i):
        fig, ax = plt.subplots(figsize=(.4,.4))
        fig.subplots_adjust(0,0,1,1)
        ax.axis("off")
        ax.axis([0,1,0,1])
        c = plt.Circle((.5,.5), .4, color=cmap(i))
        ax.add_patch(c)
        ax.text(.5,.5, str(i), ha="center", va="center")
        return fig
    
    def mapping(i):
        fig = createFigure(i)
        fname = "data/map_{}.png".format(i)
        fig.savefig(fname)
        imgstr = '<img src="{}" /> '.format(fname)
        return imgstr
    
    
    df['image'] = df['status'].map(mapping)
    df.to_html('test.html', escape=False)
    

    The drawback of this is that you have a lot of images saved somewhere on disk. If this is not desired, you may store the image encoded as base64 in the html file, <img src="data:image/png;base64,iVBORw0KGgoAAAAN..." />.

    import pandas as pd
    import numpy as np;np.random.seed(1)
    import matplotlib.pyplot as plt
    import matplotlib.colors
    from io import BytesIO
    import base64
    
    df = pd.DataFrame({"info" : np.random.randint(0,10,10), 
                       "status" : np.random.randint(0,3,10)})
    
    cmap = matplotlib.colors.ListedColormap(["crimson","orange","limegreen"])
    
    def createFigure(i):
        fig, ax = plt.subplots(figsize=(.4,.4))
        fig.subplots_adjust(0,0,1,1)
        ax.axis("off")
        ax.axis([0,1,0,1])
        c = plt.Circle((.5,.5), .4, color=cmap(i))
        ax.add_patch(c)
        ax.text(.5,.5, str(i), ha="center", va="center")
        return fig
    
    def fig2inlinehtml(fig,i):
        figfile = BytesIO()
        fig.savefig(figfile, format='png')
        figfile.seek(0) 
        # for python 2.7:
        #figdata_png = base64.b64encode(figfile.getvalue())
        # for python 3.x:
        figdata_png = base64.b64encode(figfile.getvalue()).decode()
        imgstr = '<img src="data:image/png;base64,{}" />'.format(figdata_png)
        return imgstr
    
    def mapping(i):
        fig = createFigure(i)
        return fig2inlinehtml(fig,i)
    
    
    with pd.option_context('display.max_colwidth', -1):
        df.to_html('test.html', escape=False, formatters=dict(status=mapping))
    

    The output looks the same, but there are no images saved to disk.

    This also works nicely in a Jupyter Notebook, with a small modification,

    from IPython.display import HTML
    # ...
    pd.set_option('display.max_colwidth', -1)
    HTML(df.to_html(escape=False, formatters=dict(status=mapping)))
    

    0 讨论(0)
提交回复
热议问题