Вставьте изображения matplotlib в кадр данных pandas

ЦЕЛЬ: В настоящее время я работаю с rdkit, чтобы покрасить структуры моих молекул в соответствии с rdkit.Chem.Draw.SimilarityMaps, Теперь я хотел бы использовать изображения Matplotlib SimilarityMaps функция, чтобы представить их в pandas dataframe и экспортировать эту таблицу в виде файла 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-файле.

ВОПРОС: Я не уверен, как получить фрейм данных с изображениями, и я хотел бы получить помощь сообщества, чтобы прояснить этот вопрос.

заранее спасибо

1 ответ

Решение

Что вы видите как Figure (200x200) это __repr__ строка класса рисунка matplotlib. Это текстовое представление этого объекта 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-файл, <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) 
    figdata_png = base64.b64encode(figfile.getvalue())
    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, с небольшой модификацией,

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

введите описание изображения здесь

Другие вопросы по тегам