【问题标题】:Insert matplotlib images into a pandas dataframe将 matplotlib 图像插入熊猫数据框
【发布时间】:2018-04-12 19:22:32
【问题描述】:

目的:我目前正在使用 rdkit 根据rdkit.Chem.Draw.SimilarityMaps 为我的分子结构上色。现在,我想使用 matplotlib imagesSimilarityMaps 函数将它们引入到 pandas 数据框中,并将此表以 html 文件的形式导出。

代码:我尝试使用以下代码来做到这一点

import pandas as pd
from rdkit import Chem
from rdkit.Chem import Draw
from rdkit.Chem.Draw import SimilarityMaps
from rdkit.Chem.Draw import IPythonConsole #Needed to show molecules
from rdkit.Chem.Draw.MolDrawing import MolDrawing, DrawingOptions

df = pd.DataFrame({'smiles':['Nc1nc(NC2CC2)c3ncn([C@@H]4C[C@H](CO)C=C4)c3n1','CCCC(=O)Nc1ccc(OCC(O)CNC(C)C)c(c1)C(C)=O','CCN(CC)CCNC(=O)C1=CC=C(C=C1)NC(=O)C','CC(=O)NC1=CC=C(C=C1)O','CC(=O)Nc1sc(nn1)[S](N)(=O)=O']})

def getSim(smi):
    mol = Chem.MolFromSmiles(smi)
    refmol = Chem.MolFromSmiles('c1ccccc1')
    fp = SimilarityMaps.GetMorganFingerprint(mol, fpType='bv')
    fig, maxweight = SimilarityMaps.GetSimilarityMapForFingerprint(refmol, mol, SimilarityMaps.GetMorganFingerprint)
    return fig

df['map'] = df['smiles'].map(getSim)
df.to_html('/.../test.html')

当我打开文件test.html 时,地图列包含信息“图(200x200)”。我检查我的数据框地图列是否包含对象:在 python 中可以,但在 html 文件中没有。

问题:我不确定如何获取包含图像的数据框,我希望社区能帮助我澄清这个问题。

提前致谢

【问题讨论】:

    标签: python pandas matplotlib rdkit


    【解决方案1】:

    您看到的Figure (200x200) 是matplotlib Figure 类的__repr__ 字符串。它是该 python 对象的文本表示(与您在执行print(fig) 时看到的相同)。

    您想要的是在表格中有一个实际的图像。一个简单的选择是将 matplotlib 图形保存为 png 图像,创建一个 html 标记 <img src="some.png" /> 并因此显示表格。

    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)
    

    这样做的缺点是您有很多图像保存在磁盘的某个位置。如果不需要,您可以将编码为 base64 的图像存储在 html 文件 &lt;img src="data:image/png;base64,iVBORw0KGgoAAAAN..." /&gt; 中。

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

    输出看起来相同,但没有图像保存到磁盘。

    这在 Jupyter Notebook 中也能很好地工作,只需稍作修改,

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

    【讨论】:

    • 哇...非常感谢。你的回答很酷。我找到了大致相同的解决方案,但您的解决方案更简单......我接受:)
    猜你喜欢
    • 1970-01-01
    • 2020-02-13
    • 1970-01-01
    • 2021-10-27
    • 1970-01-01
    • 2021-10-06
    • 2019-05-01
    • 1970-01-01
    相关资源
    最近更新 更多