スライドに数式や3Dのグラフを埋め込みたい

この記事は[2024年ゆる募AdventCalendar](https://adventar.org/calendars/11153)6日目（12/9分だけど...）の記事です。

# はじめに
PowerPointでスライドをつくっている時に，3次元のグラフを挿入しようとして困ったことはないでしょうか．
PowerPointだと難しいですが，**Marp**を使えば簡単にできます．

# 準備：グラフをつくる
グラフはPythonでつくります．matplotlibでも3次元のグラフは作成できますが，画像形式でしか保存できないので，今回はplotlyを用います．

とりあえず例として適当なグラフを作ります．用いるデータは以下のものです（0から1の範囲で(x,y,z)の乱数の組を発生させたもの）．
<details><summary>用いるデータ（data.csv）</summary>

```csvs:data.csv
x,y,z
0.7765197834206082,0.26926129595429993,0.5132909584693258
0.019597450386771187,0.43221700874295643,0.28532841802509146
0.18196101206254445,0.04710369687800764,0.285320092370293
0.15770532870267906,0.6909292623839551,0.9106710059795425
0.05695678239436208,0.5868888735656297,0.5785813278052875
0.019547215336652157,0.05922858677632026,0.37235845365253417
0.2178120751438658,0.2303422512723775,0.5849067257128865
0.48989183787635604,0.7295889788390598,0.7882252351479615
0.367546943689414,0.2652121504793977,0.8766129010942705
0.3489551550117256,0.04751099859744112,0.7875909912618472
0.6960400101603668,0.15475855448904152,0.10071840245640074
0.20708137020142858,0.1640874219832834,0.6585392476416415
0.9417726731793586,0.7097344833976745,0.3474387618470488
0.5167415091810094,0.5351146636759306,0.8053496061063549
0.22210548893312987,0.6286030966270205,0.5744132885666184
0.522911830663826,0.3388898598687933,0.8456012366488406
0.16440674072580297,0.09687045768782532,0.37070328900484584
0.2968974757991031,0.6356804752791378,0.9395104376722133
0.22803610145711029,0.1460577434736433,0.44458624641026256
0.35141592286005574,0.7202892021864553,0.8310097511655229
0.1676671382258934,0.14001919176099142,0.2783666352892167
0.8594607034842442,0.8979215319490934,0.07927593221190543
0.7196792559453051,0.29310260190783843,0.40668237882263536
0.7263016186186927,0.9689798944105429,0.9733900603639614
0.42847235250215476,0.6279719520728905,0.022676657703470715
0.785185031258416,0.39312678089165765,0.09881999747235215
0.5110327635608267,0.5417372463496141,0.5865526426314535
0.25666957380330235,0.5227468827551034,0.35146765155957926
0.6128190629996823,0.5873599515400354,0.47692942482153233
0.7771894939690022,0.20037843096631547,0.3119073894719425
0.3193601018590396,0.8017170285718519,0.00519052315084223
0.5173307405374137,0.6373952655679496,0.05867360829024826
0.1600262963056489,0.623621411320299,0.49902277621652846
0.1948403326919247,0.37696391038895183,0.3670972693450467
0.8250348721653823,0.15946447610126868,0.8593210479917028
0.3173982132595926,0.36253805269157036,0.6950460920860707
0.8967336370978164,0.990873109298942,0.1446767987066212
0.007633217260508696,0.4487233119714009,0.9909600311074515
0.2285042905204243,0.7109321965949733,0.17580474762373444
0.8877421012367338,0.5482356824159901,0.27046968346365885
0.39191245861221025,0.7353524365386331,0.8018274340545158
0.47243543986365455,0.7131579076115927,0.6369237692415305
0.2950682709010065,0.21600466722227973,0.9544985661295571
0.10329839874577484,0.9567681151771263,0.5207345244561474
0.08600767589190672,0.19928334215752241,0.761843528830277
0.2336252537498379,0.8582976656289181,0.8570122614203025
0.7677829676783887,0.07170113959858726,0.6648294584741363
0.11021443377975126,0.4501622301150212,0.775302657183495
0.9700981185013889,0.4342610183834975,0.010814708252600114
0.14830494659590465,0.06825586197797551,0.6760826163054577
0.6412671807460124,0.05398732259143679,0.5621125413424977
0.7296468360900386,0.19882599464330597,0.5202072354182133
0.7922696225756422,0.48763054096701663,0.7724652798064569
0.7217385110454381,0.43094621726133386,0.7520166896815321
0.5444197977259374,0.3002925975380477,0.39572621783454887
0.2640889311033946,0.2281026645541474,0.45175598515520465
0.6243516485970598,0.42972856764715817,0.21977685093220123
0.0033294225441872216,0.3131327444722509,0.11226941345113728
0.41308502935146796,0.5699162319924548,0.8327393479177331
0.997161083389796,0.5231676548783623,0.38756581816490965
0.25165866243124346,0.8968936363968648,0.38302255486015135
0.7186851754246176,0.47885598947711094,0.7393550685896593
0.694299125386195,0.7637941795698459,0.9962202057381635
0.009971220037462758,0.395290995768634,0.627118316209363
0.1562010113056045,0.37381247999600564,0.9725341402493991
0.06437736617433609,0.8221017306943533,0.11956736041130134
0.9005255256480786,0.12661960374166936,0.558153489269544
0.5637626253265159,0.7277205156299075,0.1878200318293498
0.6374141989025184,0.02207266536699526,0.14115316691406832
0.6515060247565617,0.15880225823896144,0.6163732604262853
0.3119875117487231,0.7617243252337896,0.5585044691004096
0.9918674794856098,0.6012607722912188,0.16489016039241566
0.5535664797058492,0.6200025614767977,0.6276913117539764
0.8644376125215611,0.4470396855257497,0.8306382081090488
0.2882844721057317,0.40623820173631875,0.7891848197293764
0.40833304227609324,0.9876140739914765,0.05343701954164237
0.2644858394968226,0.5170624232923136,0.9521760275051926
0.3772342719526568,0.7781038110057465,0.3796701951897209
0.9723908627651933,0.07190834338512508,0.9654920015523022
0.6618604099092612,0.5088715858102745,0.5494920811905896
0.25766182512812386,0.5862133462132194,0.43717343249103136
0.5734992829007342,0.6437314595094894,0.8695514410017494
0.0340141484548524,0.18516455195181802,0.03887422579512945
0.9393320566302713,0.01975010247807618,0.8703072348872236
0.8047678356324572,0.685376231028394,0.1192353227908407
0.3669381449341176,0.6174543007069437,0.1845588238023106
0.27261848064506755,0.5572714089539861,0.28932657055976574
0.5286465723228295,0.4274157522913231,0.6553791269845886
0.8673307067238493,0.6853983727540405,0.08981578140819091
0.21073008239051583,0.17369542550418882,0.7332540432492191
0.05938319238616041,0.28719741870334736,0.05718265197859018
0.21931143076235926,0.2960719682286813,0.3081723893474201
0.9635283438319726,0.9235575415528088,0.2671370812340026
0.791901239764337,0.38010412469056953,0.09518194844310202
0.917412760627741,0.5572041043708972,0.7504890658866589
0.9595338297105308,0.2069883118719713,0.1343986699328441
0.915986833121995,0.23867593371901552,0.5676299751960391
0.7276760841369198,0.11393493097289442,0.4444790758224445
0.7457812884292776,0.554466723793638,0.5274557284621149
0.6402479937796924,0.6570584788848438,0.25525657530168666
```
</details>

この散布図を作成するプログラムが以下です．
```python:plot.py
import pandas as pd
import plotly.graph_objects as go

# データ読み込み
df = pd.read_csv("data.csv")

# 散布図を作成
fig = go.Figure()
fig.add_trace(
    go.Scatter3d(
        x=df["x"],
        y=df["y"],
        z=df["z"],
        mode="markers",
        marker=dict(size=4)
    )
)

# タイトルや軸ラベル
fig.update_layout(
    title="3次元乱数",
    scene=dict(
        xaxis_title="X",
        yaxis_title="Y",
        zaxis_title="Z"
    ),
)

# グラフを表示
fig.show()

# グラフを保存
fig.write_html("plot.html")

```
`fig.write_html()`とすることでグラフをhtmlファイルとして保存することができます．（保存したhtmlをブラウザ等で開くことで，後からグラフを見ることができます．）

# 準備：Marpを使えるようにする
VScodeで拡張機能から「Marp for VS Code」をインストールします．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801723/8cd570c9-6b6f-1851-e2cf-162373854611.png)


インストールしたら適当なmdファイルを作成し，スライドを作ってみます．
```markdown:slide.md
---
marp: true
theme: gaia
paginate: true
---
# 1.はじめに


---
# 2.ほげほげ

---
```

実際に書いてみたらプレビューを開いてみましょう．![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801723/cf06dfb5-72ac-423c-de50-04025e116048.png)　のアイコンをで画面の右側にプレビュー画面が出ます．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801723/8d59d6af-d770-b4ea-c556-0298feeb2aeb.png)


上のようにスライド形式で表示されない場合は，![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801723/815562aa-2819-8a82-19d5-98b08aba33de.png)　のアイコンをおし，「Toggle Marp Feature For Current Markdown」を選択します．`Ctrl`+`Shift`+`P`でコマンドパレットを開き検索窓に打ち込んでもOKです．そうすると，以下のようにスライド形式でプレビューされます．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801723/91d12ddb-0bf5-a80c-2a87-a43005e80a1b.png)



`---`がページの区切りになっていて，一番最初の部分でmarpを使うことやテーマ，ページ番号の有無を設定しています．

ここまで，できれば準備完了です．

# 実際にグラフを貼り付ける
さきほど生成した`plot.html`を`<iframe>`タグで挿入すればOKです．スライド2枚目に挿入する場合は，以下のようにします．
```markdown:slide.md
---

# 2.グラフを貼る

<iframe src="plot.html" width="800pt" height="500pt"></iframe>

---
```
`width`と`height`で挿入される横幅と高さを指定できます．プレビューではグラフは表示されませんが大丈夫です．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801723/830a68d1-0f47-b64b-305a-2092aa19a3fb.png)

`<iframe src="plot.html" width="800pt" height="500pt"></iframe>`がそのまま表示されてしまう場合は，拡張機能の設定画面で以下のようにHTMLを有効にしましょう．![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801723/815562aa-2819-8a82-19d5-98b08aba33de.png)のアイコンから歯車のマークを選ぶことで設定画面を開けます．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801723/917a4ac6-ce14-d436-9b05-b3ee07e2b98f.png)


スライドが完成したら，スライドをHTML形式で保存します．コマンドパレットを開き，「Marp:Export Slide Deck」を選択します．PDF等別の形式で保存されてしまう場合は，先ほど同様，拡張機能の設定を開き，エクスポートの形式をHTMLにします．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801723/31960a64-7c2b-ac23-f89d-2e19151bcf92.png)


保存したHTMLをブラウザ等で開くと，ぐりぐり操作できる状態でスライド内に挿入できていることが確認できます．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801723/a2ea0ab0-108b-b747-8605-f3d5d108f811.png)