🗂

Dashのdatatableに画像を挿入する

2023/05/06に公開

datatableに画像を挿入する方法

Dashという簡単にデータ分析のためのダッシュボードが作れるライブラリがあります。Dashの中にはdatatableという便利なライブラリがあり、これを利用することでソートやページング、フィルターなどのテーブル形式のデータでよく用いられる機能を非常に簡単に実装することができます。

実際にダッシュボードを作成する場合、フィールドとして数値や文字列だけでなく画像やファイルへのリンクなどを使いたくなることがあります。Dashのdatatableにこれらのオブジェクトを埋め込むには実はそれなりに工夫が必要です。

実現方法1:html.ImgでImgタグを張り込む

【Dash(python)】table に画像を挿入するで紹介されている方法です。記事中ではBASE64にエンコードしてからimgタグを生成していますが、アプリ内のstaticディレクトリから参照する場合はapp.get_asset_url(img_path)のような形で参照可能です。
記事では表として、dashのdatatableではなく、dash_bootstrap_componentのテーブルを用いていますが、dash_bootstrap_componentには現時点(2021/07/11)ではページングなどのdatatableで使用できる機能を追加することはできません。

実現方法2:Markdownの画像として貼りこむ

Dashではv1.8.0からdatatableにMarkdownがサポートされました。datatableに渡すレコードをMarkdown表記のリンクにしてやることで、画像を埋め込むことができます。これは例えばdf['Img']にそれぞれの画像へのファイルパス(/static/sample.imgなど)が記載されているとして

df['Img'] = ['![data](%s)'%(app.get_asset_url(img)) for img in df['Img'].values ]

というコードを挟むことで、ファイルパスをMarkdown形式の画像挿入リンクに変換することができます。これを

path = os.getcwd()
app = dash.Dash(__name__, server=app, url_base_pathname=pathname, assets_folder=path)

df['Img'] = ['![data](%s)'%(app.get_asset_url(img)) for img in df['Img'].values ]

cols = [{"name": i, "id": j, "type":"text", "presentation":"markdown"} for i,j in zip(df, df.columns)]
app.layout = dash_table.DataTable(
    id='table',
    columns=cols,
    data=df.to_dict('records'),
    page_size = 10,
    filter_action = 'native',
    sort_action='native',
)

という形でDatatableに渡してやることで画像が埋め込まれたDatatableを作成することが可能です。画像でなくファイルへのリンクにする場合は、

df['Img'] = ['[data](%s)'%(app.get_asset_url(img)) for img in df['Img'].values ]

とすればOKです。

上記の方法で画像を埋め込んだ場合、Datatableには元の画像サイズのまま埋め込まれます。そのため、多くの場合でやたら大きい画像が埋め込まれたいまいちな感じのテーブルになります。Markdown形式で画像のサイズを調整する場合は、

df['Img'] = ['![data](%s =200x100)'%(app.get_asset_url(img)) for img in df['Img'].values ]

としたいところですが、残念ながらこの記述方法はDashでは対応していないようです・・・。

そうなると、画像の調整としては外部のCSSから対象の画像のサイズをいじることになります。やり方としては、まず下記のようにDatatableへの画像挿入時にタグ(ここではthumbnailという名前)を追加しておきます。

df['Img'] = ['![img](%s#thumbnail)'%(app.get_asset_url(img)) for img in df['Img'].values ]

その後、assetsディレクトリ(ディレクトリがない場合は作成)の中に下記のようなCSSを作成しておきます。DashのデフォルトではassetsディレクトリにあるCSSを読みに行きます。これでthumbnailという名前の画像が150px × 100pxに調整されます。

img[src*="#thumbnail"] {
   width:150px;
   height:100px;
}

上記の方法は下記の記事を参考に書いています。

https://community.plotly.com/t/resize-svg-in-markdown/48123

Discussion