Quarto 문서에서 그림 정렬하기

quarto
document-tool
그림을 마음대로 놓자!
Author

JS HUHH

Published

July 1, 2024

TL; DR

  • 그림 크기, 위치를 잡는 데에는 layout을 쓰자.
  • 이외의 미묘한 세부 조정은 css를 활용하면 된다.

의외로 잘 나오지 않는 것들

이 블로그를 포함해서 웹 문서를 만드는 데 Quarto 만큼 편하고 쉬울 툴도 드물다. 굵직한 문제들이 해결되다보면 의외로 세부적인 데 눈길이 갈 때가 있다. 그리고 그 세부적인 내용이 잘 안 찾아지면 긁을 수 없는 부위에 생긴 간지럼 마냥 계속 간지럽다. 이번에 소개할 내용이 그런 것이다.

Quarto 문서에서 어떻게 그림을 배치하는 것이 가장 효과적일까? ’효과적’이라는 말을 쓴 이유는 방법이 여러가지 있기 떄문이다. 현재의 방법이 자신의 용도와 취향에 잘 맞으면 그대로 쓰면 된다. 다만 몇 가지 문서를 만들어오면서 얻게 된 개인적인 꼼수를 나눌 뿐이다.

Reference

Quarto 문서의 그림 배치에 관한한 공식 문서에 아주 잘 소개가 되어 있다. 이 내용이면 사용자 사례의 95% 이상 포함했다고 볼 수 있을 것이다.

기본 문법

마크다운에서 그림을 배치하는 방법을 그대로 따른다. 즉,

![그림설명](리소스 주소)

응용 1: 외부 그림을 배치할 때

위 링크의 문서에 보면 layout을 활용하는 여러가지 방법이 소개되어 있다. 그중 내가 선호하는 방법은 커스텀 레이아웃이다. 활용이 어렵지도 않고 꽤 효과적이다.

 

그림 배치 사례

그림 배치 사례

 

해당 그림의 코드는 아래와 같다. 중요한 것은 layout의 명령을 구현하려면 그림 객체 사이에 줄바꿈이 있어야 한다는 것이다.

::: {layout="[[1,1], [1]]"}
![Surus](https://.png)

![Hanno](https://.png)

![Lin Wang](https://.png)
:::

응용 2: 단일 그림 배치 및 커스터마이즈

이런 복잡한 건 자주 쓰지 않고 대개는 단일한 그림을 단일하게 배치하는 경우이다. 이럴 때는 어떻게 하는 것이 좋을까? 우선 그림의 크기나 위치를 조절하는 데에는 layout을 쓰자. 다음으로 그림을 커스터마이즈해야 한다면 css를 아래와 같이 활용하는 것이 좋다.

 

Figure 1: 현재 평면을 지나는 점 \(\mathbf p_0\)를 두고 평면을 원점으로 밀어보자. 이때 평면을 정의하는 노멀 벡터 \(\vec n\)을 표현하면 원점과 이 점을 잇는 벡터 \(\vec p_0\)f를 \(\vec n\)으로 프로젝션한 벡터의 길이가 평면과 원점의 거리가 된다.

 

Figure 1 은 다음과 같은 코드로 생성했다.

:::{layout="[-5, 10, -5]"}
![현재 평면을 지나는 점 $\mathbf p_0$를 두고 평면을 원점으로 밀어보자. 이때 평면을 정의하는 노멀 벡터 $\vec n$을 표현하면 원점과 이 점을 잇는 벡터 $\vec p_0$f를 $\vec n$으로 프로젝션한 벡터의 길이가 평면과 원점의 거리가 된다.](https://github.com/anarinsk/lostineconomics-v2-1/blob/master/images/projection/plane.png?raw=true){ #fig-with-layout style="margin: auto; display: block; border:0px solid #2d2d2d;" }
:::

{style...}에 주목해보자. 이렇게 해당 부분에 css를 지정함으로써 원하는 방식으로 그림을 다룰 수 있다.

Coding Tip
  • margin: 여백 관련 옵션 ’auto’는 가운데 배치한다는 의미이다.
  • display: ’block’은 혼자 한 줄을 차지한다는 의미이다.
  • border: 테두리를 지정한다. 선의 굵기, 타입, 그리고 색을 지정할 수 있다.
  • width: 너비를 지정한다.

위의 그림에서는 너비를 지정하지 않았다. 앞서 말했듯이 너비는 layout을 써서 지정했기 때문에 여기서 중복해서 활용할 필요가 없다. 그렇다면 layout 없이 css만 써도 되지 않을까? 둘 사이의 차이를 보자.

Figure 2: 현재 평면을 지나는 점 \(\mathbf p_0\)를 두고 평면을 원점으로 밀어보자. 이때 평면을 정의하는 노멀 벡터 \(\vec n\)을 표현하면 원점과 이 점을 잇는 벡터 \(\vec p_0\)f를 \(\vec n\)으로 프로젝션한 벡터의 길이가 평면과 원점의 거리가 된다.

Figure 2Figure 1와 동일하다.

응용3: 코드 생성 그림

우선 코드에서 생성된 그림을 먼저 보자.

import numpy as np
import matplotlib.pyplot as plt

r = np.arange(0, 2, 0.01)
theta = 2 * np.pi * r
fig, ax = plt.subplots(
  subplot_kw = {'projection': 'polar'} 
)
ax.plot(theta, r)
ax.set_rticks([0.5, 1, 1.5, 2])
ax.grid(True)
plt.show()
Figure 3: A line plot on a polar axis (native Python code)

파이썬 코드에서 그림을 생성할 경우 위에서 보듯이 전체폭으로 생성된다. 아래 캡션을 보면 맨 왼쪽으로 정렬된 것을 알 수 있다. R 코드의 경우 #| fig-width:를 통해 필요한 그림의 폭을 지정할 수 있으나, 파이썬 코드의 경우 이 옵션이 유효하지 않다. 하고 싶은 것은 두 가지다.

  1. 그림의 크기를 줄이고 싶다.
  2. 캡션이 축소된 그림에 맞춰 시작되도록 하고 싶다.

아래의 코드를 보자. 이 코드는 :::{layout="[-5,10,-5]"} ... :::가 감싸고 있으며, 그림의 크기는 fig.set_size_inches(3, 3)로 지정했다. :::{layout...에 해당하는 부분은 그림의 전체적인 크기를 조절하는 데 사용한다. R의 경우 이 지정만으로 그림의 비율에 맞게 줄어드는데, 파이썬의 경우에는 이렇게 작동하지 않았다. 아래의 경우를 보자. 화면 비율이 잘 맞지 않는다는 것을 알 수 있다.

 

Figure 4: A line plot on a polar axis (with layout)

 

fig.set_size_inches()를 활용해 이를 해결할 수 있다. 이렇게 하면 그림의 크기를 줄이고 캡션도 맞출 수 있다.

import numpy as np
import matplotlib.pyplot as plt

r = np.arange(0, 2, 0.01)
theta = 2 * np.pi * r
#plt.figure(figsize=(3,3))
fig, ax = plt.subplots(
  subplot_kw = {'projection': 'polar'} 
)
ax.plot(theta, r)
ax.set_rticks([0.5, 1, 1.5, 2])
ax.grid(True)
fig.set_size_inches(4, 4)

plt.show()

 

Figure 5: A line plot on a polar axis (with layout + fig.set_size_inches()

 

아쉽게도 코드에서 생성되는 그의 경우 작동이나 문법이 아직 아쉬운 부분이 있다. 아쉬운대로 필요에 맞춰서 쓰면 되겠다.

몇 가지 질문

Caption을 가운데로 정렬할 수 있나?

🔗LINK를 보면 캡션 가운데 정렬을 일부러 막았다는 것을 알 수 있다. css를 고쳐서 구현할 수는 있으나 원래 취지를 살려두자.